Skip to content

Commit 6615954

Browse files
committed
Adding Brauer characters, fixing doctest failures, other improvements.
1 parent 515f41d commit 6615954

File tree

5 files changed

+262
-70
lines changed

5 files changed

+262
-70
lines changed

src/sage/combinat/partition.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5495,7 +5495,7 @@ def specht_module(self, base_ring=None):
54955495
EXAMPLES::
54965496
54975497
sage: SM = Partition([2,2,1]).specht_module(QQ); SM
5498-
Specht module of [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0)] over Rational Field
5498+
Specht module of [2, 2, 1] over Rational Field
54995499
sage: s = SymmetricFunctions(QQ).s()
55005500
sage: s(SM.frobenius_image()) # needs sage.modules
55015501
s[2, 2, 1]

src/sage/combinat/permutation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1263,7 +1263,7 @@ def __mul__(self, rp):
12631263
sage: p213 * SGA.an_element()
12641264
3*[1, 2, 3] + [1, 3, 2] + [2, 1, 3] + 2*[3, 1, 2]
12651265
sage: p213 * SM.an_element()
1266-
2*B[0] - 4*B[1]
1266+
2*S[[1, 2], [3]] - 4*S[[1, 3], [2]]
12671267
"""
12681268
if not isinstance(rp, Permutation) and isinstance(rp, Element):
12691269
return get_coercion_model().bin_op(self, rp, operator.mul)

src/sage/combinat/specht_module.py

Lines changed: 220 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
AUTHORS:
66
77
- Travis Scrimshaw (2023-1-22): initial version
8+
- Travis Scrimshaw (2023-11-23): added simple modules based on code
9+
from Sacha Goldman
10+
11+
.. TODO::
12+
13+
Integrate this with the implementations in
14+
:mod:`sage.modules.with_basis.representation`.
815
"""
916

1017
# ****************************************************************************
@@ -26,10 +33,10 @@
2633
from sage.matrix.constructor import matrix
2734
from sage.rings.rational_field import QQ
2835
from sage.modules.with_basis.subquotient import SubmoduleWithBasis, QuotientModuleWithBasis
36+
from sage.modules.free_module_element import vector
2937
from sage.categories.modules_with_basis import ModulesWithBasis
3038

31-
32-
class SymmetricGroupRepresentation():
39+
class SymmetricGroupRepresentation:
3340
"""
3441
Mixin class for symmetric group (algebra) representations.
3542
"""
@@ -42,48 +49,9 @@ def __init__(self, SGA):
4249
sage: SM = Partition([3,1,1]).specht_module(GF(3))
4350
sage: TestSuite(SM).run()
4451
"""
52+
self._semigroup = SGA.group()
4553
self._SGA = SGA
4654

47-
def representation_matrix(self, elt):
48-
r"""
49-
Return the matrix corresponding to the left action of the symmetric
50-
group (algebra) element ``elt`` on ``self``.
51-
52-
.. SEEALSO::
53-
54-
:class:`~sage.combinat.symmetric_group_representations.SpechtRepresentation`
55-
56-
EXAMPLES::
57-
58-
sage: SM = Partition([3,1,1]).specht_module(QQ)
59-
sage: SM.representation_matrix(Permutation([2,1,3,5,4]))
60-
[-1 0 0 0 0 0]
61-
[ 0 0 0 -1 0 0]
62-
[ 1 0 0 -1 1 0]
63-
[ 0 -1 0 0 0 0]
64-
[ 1 -1 1 0 0 0]
65-
[ 0 -1 0 1 0 -1]
66-
67-
sage: SGA = SymmetricGroupAlgebra(QQ, 5)
68-
sage: SM = SGA.specht_module([(0,0), (0,1), (0,2), (1,0), (2,0)])
69-
sage: SM.representation_matrix(Permutation([2,1,3,5,4]))
70-
[-1 0 0 1 -1 0]
71-
[ 0 0 1 0 -1 1]
72-
[ 0 1 0 -1 0 1]
73-
[ 0 0 0 0 -1 0]
74-
[ 0 0 0 -1 0 0]
75-
[ 0 0 0 0 0 -1]
76-
sage: SGA = SymmetricGroupAlgebra(QQ, 5)
77-
sage: SM.representation_matrix(SGA([3,1,5,2,4]))
78-
[ 0 -1 0 1 0 -1]
79-
[ 0 0 0 0 0 -1]
80-
[ 0 0 0 -1 0 0]
81-
[ 0 0 -1 0 1 -1]
82-
[ 1 0 0 -1 1 0]
83-
[ 0 0 0 0 1 0]
84-
"""
85-
return matrix(self.base_ring(), [(elt * b).to_vector() for b in self.basis()])
86-
8755
@cached_method
8856
def frobenius_image(self):
8957
r"""
@@ -140,11 +108,142 @@ def frobenius_image(self):
140108
from sage.combinat.sf.sf import SymmetricFunctions
141109
BR = self.base_ring()
142110
p = SymmetricFunctions(BR).p()
143-
G = self._SGA.group()
111+
G = self._semigroup
144112
CCR = [(elt, elt.cycle_type()) for elt in G.conjugacy_classes_representatives()]
145113
return p.sum(self.representation_matrix(elt).trace() / la.centralizer_size() * p[la]
146114
for elt, la in CCR)
147115

116+
# TODO: Move these methods up to methods of general representations
117+
118+
def representation_matrix(self, elt):
119+
r"""
120+
Return the matrix corresponding to the left action of the symmetric
121+
group (algebra) element ``elt`` on ``self``.
122+
123+
EXAMPLES::
124+
125+
sage: SM = Partition([3,1,1]).specht_module(QQ)
126+
sage: SM.representation_matrix(Permutation([2,1,3,5,4]))
127+
[-1 0 0 0 0 0]
128+
[ 0 0 0 -1 0 0]
129+
[ 1 0 0 -1 1 0]
130+
[ 0 -1 0 0 0 0]
131+
[ 1 -1 1 0 0 0]
132+
[ 0 -1 0 1 0 -1]
133+
134+
sage: SGA = SymmetricGroupAlgebra(QQ, 5)
135+
sage: SM = SGA.specht_module([(0,0), (0,1), (0,2), (1,0), (2,0)])
136+
sage: SM.representation_matrix(Permutation([2,1,3,5,4]))
137+
[-1 0 0 1 -1 0]
138+
[ 0 0 1 0 -1 1]
139+
[ 0 1 0 -1 0 1]
140+
[ 0 0 0 0 -1 0]
141+
[ 0 0 0 -1 0 0]
142+
[ 0 0 0 0 0 -1]
143+
sage: SGA = SymmetricGroupAlgebra(QQ, 5)
144+
sage: SM.representation_matrix(SGA([3,1,5,2,4]))
145+
[ 0 -1 0 1 0 -1]
146+
[ 0 0 0 0 0 -1]
147+
[ 0 0 0 -1 0 0]
148+
[ 0 0 -1 0 1 -1]
149+
[ 1 0 0 -1 1 0]
150+
[ 0 0 0 0 1 0]
151+
"""
152+
return matrix(self.base_ring(), [(elt * b).to_vector() for b in self.basis()])
153+
154+
@cached_method
155+
def character(self):
156+
"""
157+
Return the character of ``self``.
158+
159+
EXAMPLES::
160+
161+
sage: SGA = SymmetricGroupAlgebra(QQ, 5)
162+
sage: SM = SGA.specht_module([3,2])
163+
sage: SM.character()
164+
(5, 1, 1, -1, 1, -1, 0)
165+
sage: matrix(SGA.specht_module(la).character() for la in Partitions(5))
166+
[ 1 1 1 1 1 1 1]
167+
[ 4 2 0 1 -1 0 -1]
168+
[ 5 1 1 -1 1 -1 0]
169+
[ 6 0 -2 0 0 0 1]
170+
[ 5 -1 1 -1 -1 1 0]
171+
[ 4 -2 0 1 1 0 -1]
172+
[ 1 -1 1 1 -1 -1 1]
173+
174+
sage: SGA = SymmetricGroupAlgebra(QQ, SymmetricGroup(5))
175+
sage: SM = SGA.specht_module([3,2])
176+
sage: SM.character()
177+
Character of Symmetric group of order 5! as a permutation group
178+
sage: SM.character().values()
179+
[5, 1, 1, -1, 1, -1, 0]
180+
sage: matrix(SGA.specht_module(la).character().values() for la in reversed(Partitions(5)))
181+
[ 1 -1 1 1 -1 -1 1]
182+
[ 4 -2 0 1 1 0 -1]
183+
[ 5 -1 1 -1 -1 1 0]
184+
[ 6 0 -2 0 0 0 1]
185+
[ 5 1 1 -1 1 -1 0]
186+
[ 4 2 0 1 -1 0 -1]
187+
[ 1 1 1 1 1 1 1]
188+
sage: SGA.group().character_table()
189+
[ 1 -1 1 1 -1 -1 1]
190+
[ 4 -2 0 1 1 0 -1]
191+
[ 5 -1 1 -1 -1 1 0]
192+
[ 6 0 -2 0 0 0 1]
193+
[ 5 1 1 -1 1 -1 0]
194+
[ 4 2 0 1 -1 0 -1]
195+
[ 1 1 1 1 1 1 1]
196+
"""
197+
G = self._semigroup
198+
chi = [self.representation_matrix(g).trace()
199+
for g in G.conjugacy_classes_representatives()]
200+
try:
201+
return G.character(chi)
202+
except AttributeError:
203+
return vector(chi, immutable=True)
204+
205+
@cached_method
206+
def brauer_character(self):
207+
"""
208+
Return the Brauer character of ``self``.
209+
210+
EXAMPLES::
211+
212+
sage: SGA = SymmetricGroupAlgebra(GF(2), 5)
213+
sage: SM = SGA.specht_module([3,2])
214+
sage: SM.brauer_character()
215+
(5, -1, 0)
216+
sage: SM.simple_module().brauer_character()
217+
(4, -2, -1)
218+
"""
219+
from sage.rings.number_field.number_field import CyclotomicField
220+
from sage.arith.functions import lcm
221+
G = self._semigroup
222+
p = self.base_ring().characteristic()
223+
# We manually compute the order since a Permutation does not implement order()
224+
chi = []
225+
for g in G.conjugacy_classes_representatives():
226+
if p.divides(lcm(g.cycle_type())):
227+
# ignore the non-p-regular elements
228+
continue
229+
evals = self.representation_matrix(g).eigenvalues()
230+
K = evals[0].parent()
231+
val = 0
232+
for la in evals:
233+
if la == K.one():
234+
val += 1
235+
continue
236+
o = la.multiplicative_order()
237+
zeta = CyclotomicField(o).gen()
238+
prim = K.zeta(o)
239+
for deg in range(o):
240+
if prim**deg == la:
241+
val += zeta ** deg
242+
break
243+
chi.append(val)
244+
245+
return vector(chi, immutable=True)
246+
148247

149248
class SpechtModule(SubmoduleWithBasis, SymmetricGroupRepresentation):
150249
r"""
@@ -543,6 +642,13 @@ class SpechtModuleTableauxBasis(SpechtModule):
543642
544643
This is constructed as a `S_n`-submodule of the :class:`TabloidModule`
545644
(also referred to as the standard module).
645+
646+
.. SEEALSO::
647+
648+
- :class:`SpechtModule` for the generic diagram implementation
649+
constructed as a left ideal of the group algebra
650+
- :class:`~sage.combinat.symmetric_group_representations.SpechtRepresentation`
651+
for an implementation of the representation by matrices.
546652
"""
547653
def __init__(self, ambient):
548654
r"""
@@ -698,14 +804,25 @@ def simple_module(self):
698804
r"""
699805
Return the simple (or irreducible) `S_n`-submodule of ``self``.
700806
807+
.. SEEALSO::
808+
809+
:class:`~sage.combinat.specht_module.SimpleModule`
810+
701811
EXAMPLES::
702812
703813
sage: SGA = SymmetricGroupAlgebra(GF(3), 5)
704814
sage: SM = SGA.specht_module([3,2])
705815
sage: L = SM.simple_module()
706816
sage: L.dimension()
707817
1
818+
819+
sage: SGA = SymmetricGroupAlgebra(QQ, 5)
820+
sage: SM = SGA.specht_module([3,2])
821+
sage: SM.simple_module() is SM
822+
True
708823
"""
824+
if self.base_ring().characteristic() == 0:
825+
return self
709826
return SimpleModule(self)
710827

711828

@@ -742,13 +859,22 @@ def __init__(self, specht_module):
742859
sage: SM = SGA.specht_module([3,2])
743860
sage: U = SM.maximal_submodule()
744861
sage: TestSuite(U).run()
862+
863+
sage: SM = SGA.specht_module([2,1,1,1])
864+
sage: SM.maximal_submodule()
865+
Traceback (most recent call last):
866+
...
867+
NotImplementedError: only implemented for 3-regular partitions
745868
"""
746869
SymmetricGroupRepresentation.__init__(self, specht_module._SGA)
747870

748-
if specht_module.base_ring().characteristic() == 0:
871+
p = specht_module.base_ring().characteristic()
872+
if p == 0:
749873
basis = []
750874
else:
751875
TM = specht_module._ambient
876+
if not TM._shape.is_regular(p):
877+
raise NotImplementedError(f"only implemented for {p}-regular partitions")
752878
TV = TM._dense_free_module()
753879
SV = TV.submodule(specht_module.lift.matrix().columns())
754880
basis = (SV & SV.complement()).basis()
@@ -782,38 +908,78 @@ class SimpleModule(QuotientModuleWithBasis, SymmetricGroupRepresentation):
782908
r"""
783909
The simgle `S_n`-module associated with a partition `\lambda`.
784910
785-
The simple module `L^{\lambda}` is the quotient of the Specht module
911+
The simple module `D^{\lambda}` is the quotient of the Specht module
786912
`S^{\lambda}` by its :class:`maximal submodule <MaximalSpechtSubmodule>`
787913
`U^{\lambda}`.
788914
789915
EXAMPLES::
790916
791917
sage: SGA = SymmetricGroupAlgebra(GF(3), 5)
792918
sage: SM = SGA.specht_module([3,1,1])
793-
sage: L = SM.simple_module()
794-
sage: v = L.an_element(); v
795-
2*L[[[1, 3, 5], [2], [4]]] + 2*L[[[1, 4, 5], [2], [3]]]
919+
sage: D = SM.simple_module()
920+
sage: v = D.an_element(); v
921+
2*D[[[1, 3, 5], [2], [4]]] + 2*D[[[1, 4, 5], [2], [3]]]
796922
sage: SGA.an_element() * v
797-
2*L[[[1, 2, 4], [3], [5]]] + 2*L[[[1, 3, 5], [2], [4]]]
923+
2*D[[[1, 2, 4], [3], [5]]] + 2*D[[[1, 3, 5], [2], [4]]]
924+
925+
We give an example on how to construct the decomposition matrix
926+
(the Specht modules are a complete set of irreducible projective
927+
modules) and the Cartan matrix of a symmetric group algebra::
928+
929+
sage: SGA = SymmetricGroupAlgebra(GF(3), 4)
930+
sage: BM = matrix(SGA.simple_module(la).brauer_character()
931+
....: for la in Partitions(4, regular=3))
932+
sage: SBT = matrix(SGA.specht_module(la).brauer_character()
933+
....: for la in Partitions(4))
934+
sage: D = SBT * ~BM; D
935+
[1 0 0 0]
936+
[0 1 0 0]
937+
[1 0 1 0]
938+
[0 0 0 1]
939+
[0 0 1 0]
940+
sage: D.transpose() * D
941+
[2 0 1 0]
942+
[0 1 0 0]
943+
[1 0 2 0]
944+
[0 0 0 1]
945+
946+
We verify this against the direct computation (up to reindexing the
947+
rows and columns)::
948+
949+
sage: SGA.cartan_invariants_matrix() # long time
950+
[1 0 0 0]
951+
[0 1 0 0]
952+
[0 0 2 1]
953+
[0 0 1 2]
798954
"""
799955
def __init__(self, specht_module):
800-
"""
956+
r"""
801957
Initialize ``self``.
802958
803959
EXAMPLES::
804960
805961
sage: SGA = SymmetricGroupAlgebra(GF(3), 5)
806962
sage: SM = SGA.specht_module([3,1,1])
807-
sage: L = SM.simple_module()
808-
sage: TestSuite(L).run()
963+
sage: D = SM.simple_module()
964+
sage: TestSuite(D).run()
965+
966+
sage: SGA = SymmetricGroupAlgebra(GF(3), 5)
967+
sage: SM = SGA.specht_module([2,1,1,1])
968+
sage: SM.simple_module()
969+
Traceback (most recent call last):
970+
...
971+
ValueError: the partition must be 3-regular
809972
"""
810973
self._diagram = specht_module._diagram
974+
p = specht_module.base_ring().characteristic()
975+
if not self._diagram.is_regular(p):
976+
raise ValueError(f"the partition must be {p}-regular")
811977
SymmetricGroupRepresentation.__init__(self, specht_module._SGA)
812978
cat = specht_module.category()
813-
QuotientModuleWithBasis.__init__(self, specht_module.maximal_submodule(), cat, prefix='L')
979+
QuotientModuleWithBasis.__init__(self, specht_module.maximal_submodule(), cat, prefix='D')
814980

815981
def _repr_(self):
816-
"""
982+
r"""
817983
Return a string representation of ``self``.
818984
819985
EXAMPLES::

0 commit comments

Comments
 (0)