Skip to content

Commit

Permalink
Implementing Holt-Rees meataxe, subquotient reprs, adding duplication.
Browse files Browse the repository at this point in the history
  • Loading branch information
tscrim committed Apr 21, 2024
1 parent 69678a0 commit 3ddf4b9
Show file tree
Hide file tree
Showing 7 changed files with 754 additions and 204 deletions.
16 changes: 9 additions & 7 deletions src/sage/categories/modules_with_basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ def echelon_form(self, elements, row_reduced=False, order=None):

def submodule(self, gens, check=True, already_echelonized=False,
unitriangular=False, support_order=None, category=None,
*args, **opts):
parent_class=None, *args, **opts):
r"""
The submodule spanned by a finite set of elements.
Expand All @@ -744,6 +744,7 @@ def submodule(self, gens, check=True, already_echelonized=False,
- ``support_order`` -- (optional) either something that can
be converted into a tuple or a key function
- ``category`` -- (optional) the category of the submodule
- ``parent_class`` -- (optional) the class of the parent to return
If ``already_echelonized`` is ``False``, then the
generators are put in reduced echelon form using
Expand Down Expand Up @@ -906,11 +907,12 @@ def submodule(self, gens, check=True, already_echelonized=False,
if not already_echelonized:
gens = self.echelon_form(gens, unitriangular, order=support_order)

from sage.modules.with_basis.subquotient import SubmoduleWithBasis
return SubmoduleWithBasis(gens, ambient=self,
support_order=support_order,
unitriangular=unitriangular,
category=category, *args, **opts)
if parent_class is None:
from sage.modules.with_basis.subquotient import SubmoduleWithBasis as parent_class
return parent_class(gens, ambient=self,
support_order=support_order,
unitriangular=unitriangular,
category=category, *args, **opts)

def quotient_module(self, submodule, check=True, already_echelonized=False, category=None):
r"""
Expand Down Expand Up @@ -1075,7 +1077,7 @@ def is_finite(self):
sage: GroupAlgebra(AbelianGroup(1), IntegerModRing(10)).is_finite() # needs sage.groups sage.modules
False
"""
return (self.base_ring().is_finite() and self.group().is_finite())
return (self.base_ring().is_finite() and self.basis().keys().is_finite())

def monomial(self, i):
"""
Expand Down
29 changes: 29 additions & 0 deletions src/sage/combinat/partition.py
Original file line number Diff line number Diff line change
Expand Up @@ -5620,6 +5620,35 @@ def specht_module(self, base_ring=None):
R = SymmetricGroupAlgebra(base_ring, sum(self))
return SpechtModule(R, self)

def garsia_procesi_module(self, base_ring=None):
r"""
Return the :class:`Garsia-Procesi module
<sage.combinat.symmetric_group_representations.GarsiaProcesiModule>`
corresponding to ``self``.
INPUT:
- ``base_ring`` -- (default: `\QQ`) the base ring
EXAMPLES::
sage: GP = Partition([3,2,1]).garsia_procesi_module(QQ); GP
Garsia-Procesi module of shape [3, 2, 1] over Rational Field
sage: GP.graded_frobenius_image()
q^4*s[3, 2, 1] + q^3*s[3, 3] + q^3*s[4, 1, 1] + (q^3+q^2)*s[4, 2]
+ (q^2+q)*s[5, 1] + s[6]
sage: Partition([3,2,1]).garsia_procesi_module(GF(3))
Garsia-Procesi module of shape [3, 2, 1] over Finite Field of size 3
"""
from sage.combinat.symmetric_group_representations import GarsiaProcesiModule
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 GarsiaProcesiModule(R, self)

def specht_module_dimension(self, base_ring=None):
r"""
Return the dimension of the Specht module corresponding to ``self``.
Expand Down
162 changes: 8 additions & 154 deletions src/sage/combinat/specht_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,33 +37,22 @@
from sage.modules.free_module_element import vector
from sage.categories.modules_with_basis import ModulesWithBasis

class SymmetricGroupRepresentation:
class SymmetricGroupRepresentation(Representation_abstract):
"""
Mixin class for symmetric group (algebra) representations.
"""
def __init__(self, SGA):
"""
Initialize ``self``.
EXAMPLES::
sage: SM = Partition([3,1,1]).specht_module(GF(3))
sage: TestSuite(SM).run()
"""
self._semigroup = SGA.group()
self._semigroup_algebra = SGA

def side(self):
r"""
Return the side of the action defining ``self``.
EXAMPLES::
sage: SM = Partition([3,1,1]).specht_module(GF(3))
sage: SM.side()
'left'
sage: TestSuite(SM).run()
"""
return "left"
Representation_abstract.__init__(self, SGA.group(), "left", SGA)

@cached_method
def frobenius_image(self):
Expand Down Expand Up @@ -127,143 +116,8 @@ def frobenius_image(self):
return s(p.sum(QQ(sum((elt * B[k])[k] for k in B.keys())) / la.centralizer_size() * p[la]
for elt, la in CCR))

# TODO: Move these methods up to methods of general representations

def representation_matrix(self, elt):
r"""
Return the matrix corresponding to the left action of the symmetric
group (algebra) element ``elt`` on ``self``.
EXAMPLES::
sage: SM = Partition([3,1,1]).specht_module(QQ)
sage: SM.representation_matrix(Permutation([2,1,3,5,4]))
[-1 0 0 0 0 0]
[ 0 0 0 -1 0 0]
[ 1 0 0 -1 1 0]
[ 0 -1 0 0 0 0]
[ 1 -1 1 0 0 0]
[ 0 -1 0 1 0 -1]
sage: SGA = SymmetricGroupAlgebra(QQ, 5)
sage: SM = SGA.specht_module([(0,0), (0,1), (0,2), (1,0), (2,0)])
sage: SM.representation_matrix(Permutation([2,1,3,5,4]))
[-1 0 0 1 -1 0]
[ 0 0 1 0 -1 1]
[ 0 1 0 -1 0 1]
[ 0 0 0 0 -1 0]
[ 0 0 0 -1 0 0]
[ 0 0 0 0 0 -1]
sage: SGA = SymmetricGroupAlgebra(QQ, 5)
sage: SM.representation_matrix(SGA([3,1,5,2,4]))
[ 0 -1 0 1 0 -1]
[ 0 0 0 0 0 -1]
[ 0 0 0 -1 0 0]
[ 0 0 -1 0 1 -1]
[ 1 0 0 -1 1 0]
[ 0 0 0 0 1 0]
"""
return matrix(self.base_ring(), [(elt * b).to_vector() for b in self.basis()])

@cached_method
def character(self):
r"""
Return the character of ``self``.

EXAMPLES::
sage: SGA = SymmetricGroupAlgebra(QQ, 5)
sage: SM = SGA.specht_module([3,2])
sage: SM.character()
(5, 1, 1, -1, 1, -1, 0)
sage: matrix(SGA.specht_module(la).character() for la in Partitions(5))
[ 1 1 1 1 1 1 1]
[ 4 2 0 1 -1 0 -1]
[ 5 1 1 -1 1 -1 0]
[ 6 0 -2 0 0 0 1]
[ 5 -1 1 -1 -1 1 0]
[ 4 -2 0 1 1 0 -1]
[ 1 -1 1 1 -1 -1 1]
sage: SGA = SymmetricGroupAlgebra(QQ, SymmetricGroup(5))
sage: SM = SGA.specht_module([3,2])
sage: SM.character()
Character of Symmetric group of order 5! as a permutation group
sage: SM.character().values()
[5, 1, 1, -1, 1, -1, 0]
sage: matrix(SGA.specht_module(la).character().values() for la in reversed(Partitions(5)))
[ 1 -1 1 1 -1 -1 1]
[ 4 -2 0 1 1 0 -1]
[ 5 -1 1 -1 -1 1 0]
[ 6 0 -2 0 0 0 1]
[ 5 1 1 -1 1 -1 0]
[ 4 2 0 1 -1 0 -1]
[ 1 1 1 1 1 1 1]
sage: SGA.group().character_table()
[ 1 -1 1 1 -1 -1 1]
[ 4 -2 0 1 1 0 -1]
[ 5 -1 1 -1 -1 1 0]
[ 6 0 -2 0 0 0 1]
[ 5 1 1 -1 1 -1 0]
[ 4 2 0 1 -1 0 -1]
[ 1 1 1 1 1 1 1]
"""
G = self._semigroup
B = self.basis()
chi = [sum((g * B[k])[k] for k in B.keys())
for g in G.conjugacy_classes_representatives()]
try:
return G.character(chi)
except AttributeError:
return vector(chi, immutable=True)

@cached_method
def brauer_character(self):
r"""
Return the Brauer character of ``self``.
EXAMPLES::
sage: SGA = SymmetricGroupAlgebra(GF(2), 5)
sage: SM = SGA.specht_module([3,2])
sage: SM.brauer_character()
(5, -1, 0)
sage: SM.simple_module().brauer_character()
(4, -2, -1)
"""
from sage.rings.number_field.number_field import CyclotomicField
from sage.arith.functions import lcm
G = self._semigroup
p = self.base_ring().characteristic()
# We manually compute the order since a Permutation does not implement order()
chi = []
for g in G.conjugacy_classes_representatives():
if p.divides(lcm(g.cycle_type())):
# ignore the non-p-regular elements
continue
evals = self.representation_matrix(g).eigenvalues()
K = evals[0].parent()
val = 0
orders = {la: la.multiplicative_order() for la in evals if la != K.one()}
zetas = {o: CyclotomicField(o).gen() for o in orders.values()}
prims = {o: K.zeta(o) for o in orders.values()}
for la in evals:
if la == K.one():
val += 1
continue
o = la.multiplicative_order()
zeta = zetas[o]
prim = prims[o]
for deg in range(o):
if prim ** deg == la:
val += zeta ** deg
break
chi.append(val)

return vector(chi, immutable=True)


class SpechtModule(SubmoduleWithBasis, SymmetricGroupRepresentation, Representation_abstract):
class SpechtModule(SymmetricGroupRepresentation, SubmoduleWithBasis):
r"""
A Specht module.
Expand Down Expand Up @@ -543,7 +397,7 @@ def _acted_upon_(self, x, self_on_left=False):
return None


class TabloidModule(SymmetricGroupRepresentation, Representation_abstract):
class TabloidModule(SymmetricGroupRepresentation, CombinatorialFreeModule):
r"""
The vector space of all tabloids of a fixed shape with the natural
symmetric group action.
Expand Down Expand Up @@ -800,7 +654,7 @@ def _acted_upon_(self, x, self_on_left):
return None
P = self.parent()
if x in P._semigroup_algebra:
return P.sum(c * (perm * self) for perm, c in x.monomial_coefficients().items())
return P.linear_combination((perm * self, c) for perm, c in x.monomial_coefficients().items())
if x in P._semigroup_algebra.indices():
return P.element_class(P, {P._symmetric_group_action(T, x): c
for T, c in self._monomial_coefficients.items()})
Expand Down Expand Up @@ -997,7 +851,7 @@ def simple_module(self):
return SimpleModule(self)


class MaximalSpechtSubmodule(SubmoduleWithBasis, SymmetricGroupRepresentation):
class MaximalSpechtSubmodule(SymmetricGroupRepresentation, SubmoduleWithBasis):
r"""
The maximal submodule `U^{\lambda}` of the Specht module `S^{\lambda}`.
Expand Down Expand Up @@ -1082,7 +936,7 @@ def _repr_(self):
Element = SpechtModule.Element


class SimpleModule(QuotientModuleWithBasis, SymmetricGroupRepresentation):
class SimpleModule(SymmetricGroupRepresentation, QuotientModuleWithBasis):
r"""
The simgle `S_n`-module associated with a partition `\lambda`.
Expand Down
42 changes: 37 additions & 5 deletions src/sage/combinat/symmetric_group_algebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from sage.combinat.free_module import CombinatorialFreeModule
from sage.combinat.permutation import Permutation, Permutations, from_permutation_group_element
from sage.combinat.permutation_cython import (left_action_same_n, right_action_same_n)
from sage.combinat.partition import _Partitions, Partitions_n
from sage.combinat.partition import _Partitions, Partitions, Partitions_n
from sage.combinat.tableau import Tableau, StandardTableaux_size, StandardTableaux_shape, StandardTableaux
from sage.algebras.group_algebra import GroupAlgebra_class
from sage.algebras.cellular_basis import CellularBasis
Expand Down Expand Up @@ -294,6 +294,10 @@ def __init__(self, R, W, category):
GroupAlgebra_class.__init__(self, R, W, prefix='',
latex_prefix='', category=category)

# Mixin class for extra methods for representations
from sage.combinat.specht_module import SymmetricGroupRepresentation
self._representation_mixin_class = SymmetricGroupRepresentation

def _repr_(self):
"""
Return a string representation of ``self``.
Expand Down Expand Up @@ -1623,6 +1627,28 @@ def specht_module_dimension(self, D):
span_set = specht_module_spanning_set(D, self)
return matrix(self.base_ring(), [v.to_vector() for v in span_set]).rank()

def simple_module_parameterization(self):
r"""
Return a parameterization of the simple modules of ``self``.
The symmetric group algebra of `S_n` over a field of characteristic `p`
has its simple modules indexed by all `p`-regular partitions of `n`.
EXAMPLES::
sage: SGA = SymmetricGroupAlgebra(QQ, 6)
sage: SGA.simple_module_parameterization()
Partitions of the integer 6
sage: SGA = SymmetricGroupAlgebra(GF(2), 6)
sage: SGA.simple_module_parameterization()
2-Regular Partitions of the integer 6
"""
p = self.base_ring().characteristic()
if p > 0:
return Partitions(self.n, regular=p)
return Partitions_n(self.n)

def simple_module(self, la):
r"""
Return the simple module of ``self`` indexed by the partition ``la``.
Expand Down Expand Up @@ -1671,11 +1697,17 @@ def simple_module_dimension(self, la):
return simple_module_rank(la, self.base_ring())

def garsia_procesi_module(self, la):
r"""
Return the :class:`Garsia-Procesi module
<sage.combinat.symmetric_group_representations.GarsiaProcesiModule>`
of ``self`` indexed by ``la``.
EXAMPLES::
sage: SGA = SymmetricGroupAlgebra(GF(2), 6)
sage: SGA.garsia_procesi_module(Partition([2,2,1,1]))
Garsia-Procesi module of shape [2, 2, 1, 1] over Finite Field of size 2
"""
Return the Garsia-Procesi module of ``self`` indexed by ``la``.
"""
if sum(la) != self.n:
raise ValueError(f"{la} is not a partition of {self.n}")
from sage.combinat.symmetric_group_representations import GarsiaProcesiModule
return GarsiaProcesiModule(self, la)

Expand Down
Loading

0 comments on commit 3ddf4b9

Please sign in to comment.