Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
gh-35036: Implement Specht modules for diagrams
    
Fixes #34883.
    
URL: #35036
Reported by: Travis Scrimshaw
Reviewer(s): Frédéric Chapoton, Travis Scrimshaw
  • Loading branch information
Release Manager committed Mar 31, 2023
2 parents 82e02a1 + ff7bc98 commit b5d509b
Show file tree
Hide file tree
Showing 10 changed files with 737 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/doc/en/reference/combinat/module_list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ Comprehensive Module List
sage/combinat/species/structure
sage/combinat/species/subset_species
sage/combinat/species/sum_species
sage/combinat/specht_module
sage/combinat/subset
sage/combinat/subsets_hereditary
sage/combinat/subsets_pairwise
Expand Down
1 change: 1 addition & 0 deletions src/sage/combinat/algebraic_combinatorics.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
- :ref:`sage.combinat.cluster_algebra_quiver.all`
- :class:`~sage.combinat.kazhdan_lusztig.KazhdanLusztigPolynomial`
- :class:`~sage.combinat.symmetric_group_representations.SymmetricGroupRepresentation`
- :class:`~sage.combinat.specht_module.SpechtModule`
- :ref:`sage.combinat.yang_baxter_graph`
- :ref:`sage.combinat.hall_polynomial`
- :ref:`sage.combinat.key_polynomial`
Expand Down
42 changes: 42 additions & 0 deletions src/sage/combinat/composition.py
Original file line number Diff line number Diff line change
Expand Up @@ -1386,6 +1386,48 @@ def count(self, n):
"""
return sum(i == n for i in self)

def specht_module(self, base_ring=None):
r"""
Return the Specht module corresponding to ``self``.
EXAMPLES::
sage: SM = Composition([1,2,2]).specht_module(QQ)
sage: SM
Specht module of [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)] over Rational Field
sage: s = SymmetricFunctions(QQ).s()
sage: s(SM.frobenius_image())
s[2, 2, 1]
"""
from sage.combinat.specht_module import SpechtModule
from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra
if base_ring is None:
from sage.rings.rational_field import QQ
base_ring = QQ
R = SymmetricGroupAlgebra(base_ring, sum(self))
cells = []
for i, row in enumerate(self):
for j in range(row):
cells.append((i, j))
return SpechtModule(R, cells)

def specht_module_dimension(self, base_ring=None):
r"""
Return the dimension of the Specht module corresponding to ``self``.
INPUT:
- ``base_ring`` -- (default: `\QQ`) the base ring
EXAMPLES::
sage: Composition([1,2,2]).specht_module_dimension()
5
sage: Composition([1,2,2]).specht_module_dimension(GF(2))
5
"""
from sage.combinat.specht_module import specht_module_rank
return specht_module_rank(self, base_ring)

Sequence.register(Composition)
##############################################################
Expand Down
40 changes: 40 additions & 0 deletions src/sage/combinat/diagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,46 @@ def check(self):
if not all(all(list(i in NN for i in c)) for c in self._cells):
raise ValueError("Diagrams must be indexed by non-negative integers")

def specht_module(self, base_ring=None):
r"""
Return the Specht module corresponding to ``self``.
EXAMPLES::
sage: from sage.combinat.diagram import Diagram
sage: D = Diagram([(0,0), (1,1), (2,2), (2,3)])
sage: SM = D.specht_module(QQ)
sage: s = SymmetricFunctions(QQ).s()
sage: s(SM.frobenius_image())
s[2, 1, 1] + s[2, 2] + 2*s[3, 1] + s[4]
"""
from sage.combinat.specht_module import SpechtModule
from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra
if base_ring is None:
from sage.rings.rational_field import QQ
base_ring = QQ
R = SymmetricGroupAlgebra(base_ring, len(self))
return SpechtModule(R, self)

def specht_module_dimension(self, base_ring=None):
r"""
Return the dimension of the Specht module corresponding to ``self``.
INPUT:
- ``base_ring`` -- (default: `\QQ`) the base ring
EXAMPLES::
sage: from sage.combinat.diagram import Diagram
sage: D = Diagram([(0,0), (1,1), (2,2), (2,3)])
sage: D.specht_module_dimension()
12
sage: D.specht_module(QQ).dimension()
12
"""
from sage.combinat.specht_module import specht_module_rank
return specht_module_rank(self, base_ring)

class Diagrams(UniqueRepresentation, Parent):
r"""
Expand Down
39 changes: 39 additions & 0 deletions src/sage/combinat/integer_vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,45 @@ def trim(self):
v = v[:-1]
return P.element_class(P, v, check=False)

def specht_module(self, base_ring=None):
r"""
Return the Specht module corresponding to ``self``.
EXAMPLES::
sage: SM = IntegerVectors()([2,0,1,0,2]).specht_module(QQ)
sage: SM
Specht module of [(0, 0), (0, 1), (2, 0), (4, 0), (4, 1)] over Rational Field
sage: s = SymmetricFunctions(QQ).s()
sage: s(SM.frobenius_image())
s[2, 2, 1]
"""
from sage.combinat.specht_module import SpechtModule
from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra
if base_ring is None:
from sage.rings.rational_field import QQ
base_ring = QQ
R = SymmetricGroupAlgebra(base_ring, sum(self))
return SpechtModule(R, self)

def specht_module_dimension(self, base_ring=None):
r"""
Return the dimension of the Specht module corresponding to ``self``.
INPUT:
- ``BR`` -- (default: `\QQ`) the base ring
EXAMPLES::
sage: IntegerVectors()([2,0,1,0,2]).specht_module_dimension()
5
sage: IntegerVectors()([2,0,1,0,2]).specht_module_dimension(GF(2))
5
"""
from sage.combinat.specht_module import specht_module_rank
return specht_module_rank(self, base_ring)


class IntegerVectors(Parent, metaclass=ClasscallMetaclass):
"""
Expand Down
46 changes: 46 additions & 0 deletions src/sage/combinat/partition.py
Original file line number Diff line number Diff line change
Expand Up @@ -5483,6 +5483,52 @@ def coloring(i):
immutable=True, multiedges=True)
return self.dual_equivalence_graph(directed, coloring)

def specht_module(self, base_ring=None):
r"""
Return the Specht module corresponding to ``self``.
EXAMPLES::
sage: SM = Partition([2,2,1]).specht_module(QQ)
sage: SM
Specht module of [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0)] over Rational Field
sage: s = SymmetricFunctions(QQ).s()
sage: s(SM.frobenius_image())
s[2, 2, 1]
"""
from sage.combinat.specht_module import SpechtModule
from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra
if base_ring is None:
from sage.rings.rational_field import QQ
base_ring = QQ
R = SymmetricGroupAlgebra(base_ring, sum(self))
return SpechtModule(R, self)

def specht_module_dimension(self, base_ring=None):
r"""
Return the dimension of the Specht module corresponding to ``self``.
This is equal to the number of standard tableaux of shape ``self`` when
over a field of characteristic `0`.
INPUT:
- ``BR`` -- (default: `\QQ`) the base ring
EXAMPLES::
sage: Partition([2,2,1]).specht_module_dimension()
5
sage: Partition([2,2,1]).specht_module_dimension(GF(2))
5
"""
from sage.categories.fields import Fields
if base_ring is None or (base_ring in Fields() and base_ring.characteristic() == 0):
from sage.combinat.tableau import StandardTableaux
return StandardTableaux(self).cardinality()
from sage.combinat.specht_module import specht_module_rank
return specht_module_rank(self, base_ring)


##############
# Partitions #
Expand Down
34 changes: 28 additions & 6 deletions src/sage/combinat/permutation.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,9 @@
from sage.structure.global_options import GlobalOptions
from sage.structure.list_clone import ClonableArray
from sage.structure.parent import Parent
from sage.structure.element import Element, get_coercion_model
from sage.structure.unique_representation import UniqueRepresentation

import operator

class Permutation(CombinatorialElement):
r"""
Expand Down Expand Up @@ -1242,7 +1243,23 @@ def to_alternating_sign_matrix(self):
from sage.combinat.alternating_sign_matrix import AlternatingSignMatrix
return AlternatingSignMatrix(self.to_matrix().rows())

def __mul__(self, rp) -> Permutation:
def __mul__(self, rp):
"""
TESTS::
sage: SGA = SymmetricGroupAlgebra(QQ, 3)
sage: SM = SGA.specht_module([2,1])
sage: p213 = Permutations(3)([2,1,3])
sage: p213 * SGA.an_element()
3*[1, 2, 3] + [1, 3, 2] + [2, 1, 3] + 2*[3, 1, 2]
sage: p213 * SM.an_element()
2*B[0] - 4*B[1]
"""
if not isinstance(rp, Permutation) and isinstance(rp, Element):
return get_coercion_model().bin_op(self, rp, operator.mul)
return Permutation._mul_(self, rp)

def _mul_(self, rp) -> Permutation:
"""
TESTS::
Expand All @@ -1261,8 +1278,6 @@ def __mul__(self, rp) -> Permutation:
else:
return self._left_to_right_multiply_on_left(rp)

_mul_ = __mul__ # For ``prod()``

def __rmul__(self, lp) -> Permutation:
"""
TESTS::
Expand All @@ -1276,7 +1291,13 @@ def __rmul__(self, lp) -> Permutation:
sage: p213*p312
[3, 2, 1]
sage: Permutations.options.mult='l2r'
sage: SGA = SymmetricGroupAlgebra(QQ, 3)
sage: SGA.an_element() * Permutations(3)(p213)
3*[1, 2, 3] + [2, 1, 3] + 2*[2, 3, 1] + [3, 2, 1]
"""
if not isinstance(lp, Permutation) and isinstance(lp, Element):
return get_coercion_model().bin_op(lp, self, operator.mul)
if self.parent().options.mult == 'l2r':
return self._left_to_right_multiply_on_left(lp)
else:
Expand Down Expand Up @@ -7328,9 +7349,10 @@ def __mul__(self, other):
"""
if not isinstance(other, StandardPermutations_n.Element):
return Permutation.__mul__(self, other)
if other.parent() is not self.parent():
P = self.parent()
if other.parent() is not P:
# They have different parents (but both are (like) Permutations of n)
mul_order = self.parent().options.mult
mul_order = P.options.mult
if mul_order == 'l2r':
p = right_action_product(self._list, other._list)
elif mul_order == 'r2l':
Expand Down
57 changes: 57 additions & 0 deletions src/sage/combinat/skew_partition.py
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,63 @@ def outside_corners(self):
"""
return self.outer().outside_corners()

def specht_module(self, base_ring=None):
r"""
Return the Specht module corresponding to ``self``.
EXAMPLES::
sage: mu = SkewPartition([[3,2,1], [2]])
sage: SM = mu.specht_module(QQ)
sage: s = SymmetricFunctions(QQ).s()
sage: s(SM.frobenius_image())
s[2, 1, 1] + s[2, 2] + s[3, 1]
We verify that the Frobenius image is the corresponding
skew Schur function::
sage: s[3,2,1].skew_by(s[2])
s[2, 1, 1] + s[2, 2] + s[3, 1]
::
sage: mu = SkewPartition([[4,2,1], [2,1]])
sage: SM = mu.specht_module(QQ)
sage: s(SM.frobenius_image())
s[2, 1, 1] + s[2, 2] + 2*s[3, 1] + s[4]
sage: s(mu)
s[2, 1, 1] + s[2, 2] + 2*s[3, 1] + s[4]
"""
from sage.combinat.specht_module import SpechtModule
from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra
if base_ring is None:
from sage.rings.rational_field import QQ
base_ring = QQ
R = SymmetricGroupAlgebra(base_ring, self.size())
return SpechtModule(R, self.cells())

def specht_module_dimension(self, base_ring=None):
r"""
Return the dimension of the Specht module corresponding to ``self``.
This is equal to the number of standard (skew) tableaux of
shape ``self``.
EXAMPLES::
sage: mu = SkewPartition([[3,2,1], [2]])
sage: mu.specht_module_dimension()
8
sage: mu.specht_module_dimension(GF(2))
8
"""
from sage.categories.fields import Fields
if base_ring is None or (base_ring in Fields() and base_ring.characteristic() == 0):
from sage.combinat.skew_tableau import StandardSkewTableaux
return StandardSkewTableaux(self).cardinality()
from sage.combinat.specht_module import specht_module_rank
return specht_module_rank(self, base_ring)


def row_lengths_aux(skp):
"""
Expand Down
Loading

0 comments on commit b5d509b

Please sign in to comment.