From 5aab2296ec62a5b2b9548110d0cfc276558c330e Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 15 Nov 2023 17:11:20 +0900 Subject: [PATCH] Porting code from Jackson Walters to compute dimensions of simple modules over positive characteristics. --- src/sage/combinat/partition.py | 39 +++++++- src/sage/combinat/specht_module.py | 94 ++++++++++++++++++++ src/sage/combinat/symmetric_group_algebra.py | 20 +++++ src/sage/combinat/tableau.py | 11 ++- 4 files changed, 162 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/partition.py b/src/sage/combinat/partition.py index 742f9a93917..28248cc3a7a 100644 --- a/src/sage/combinat/partition.py +++ b/src/sage/combinat/partition.py @@ -5513,7 +5513,7 @@ def specht_module_dimension(self, base_ring=None): INPUT: - - ``BR`` -- (default: `\QQ`) the base ring + - ``base_ring`` -- (default: `\QQ`) the base ring EXAMPLES:: @@ -5529,6 +5529,43 @@ def specht_module_dimension(self, base_ring=None): from sage.combinat.specht_module import specht_module_rank return specht_module_rank(self, base_ring) + def simple_module_dimension(self, base_ring=None): + r""" + Return the dimension of the simple module corresponding to ``self``. + + This is equal to the dimension of the Specht module over a field + of characteristic `0`. + + INPUT: + + - ``base_ring`` -- (default: `\QQ`) the base ring + + EXAMPLES:: + + sage: Partition([2,2,1]).simple_module_dimension() + 5 + sage: Partition([2,2,1]).specht_module_dimension(GF(3)) # optional - sage.rings.finite_rings + 5 + sage: Partition([2,2,1]).simple_module_dimension(GF(3)) # optional - sage.rings.finite_rings + 4 + + sage: for la in Partitions(6, regular=3): + ....: print(la, la.specht_module_dimension(), la.simple_module_dimension(GF(3))) + [6] 1 1 + [5, 1] 5 4 + [4, 2] 9 9 + [4, 1, 1] 10 6 + [3, 3] 5 1 + [3, 2, 1] 16 4 + [2, 2, 1, 1] 9 9 + """ + 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 simple_module_rank + return simple_module_rank(self, base_ring) + ############## # Partitions # diff --git a/src/sage/combinat/specht_module.py b/src/sage/combinat/specht_module.py index 678933d78fb..577dd0ecfce 100644 --- a/src/sage/combinat/specht_module.py +++ b/src/sage/combinat/specht_module.py @@ -456,3 +456,97 @@ def specht_module_rank(D, base_ring=None): if base_ring is None: base_ring = QQ return matrix(base_ring, [v.to_vector() for v in span_set]).rank() + + +def polytabloid(T): + r""" + Compute the polytabloid element associated to a tableau ``T``. + + For a tableau `T`, the polytabloid associated to `T` is + + .. MATH:: + + e_T = \sum_{\sigma \in C_T} (-1)^{\sigma} \{\sigma T\}, + + where `\{\}` is the row-equivalence class, i.e. a tabloid, + and `C_T` is the column stabilizer of `T`. The sum takes place in + the module spanned by tabloids `\{T\}`. + + OUTPUT: + + A ``dict`` whose keys are taboids represented by tuples of frozensets + and whose values are the coefficient. + + EXAMPLES:: + + sage: from sage.combinat.specht_module import polytabloid + sage: T = StandardTableau([[1,3,4],[2,5]]) + sage: polytabloid(T) + {(frozenset({1, 3, 4}), frozenset({2, 5})): 1, + (frozenset({1, 4, 5}), frozenset({2, 3})): -1, + (frozenset({2, 3, 4}), frozenset({1, 5})): -1, + (frozenset({2, 4, 5}), frozenset({1, 3})): 1} + """ + e_T = {} + C_T = T.column_stabilizer() + for perm in C_T: + TT = tuple([frozenset(perm(val) for val in row) for row in T]) + if TT in e_T: + e_T[TT] += perm.sign() + else: + e_T[TT] = perm.sign() + return e_T + + +def tabloid_gram_matrix(la, base_ring): + r""" + Compute the Gram matrix of the bilinear form of a Specht module + pulled back from the tabloid module. + + For the module spanned by all tabloids, we define an bilinear form + by having the taboids be an orthonormal basis. We then pull this + bilinear form back across the natural injection of the Specht module + into the tabloid module. + + EXAMPLES:: + + sage: from sage.combinat.specht_module import tabloid_gram_matrix + sage: tabloid_gram_matrix([3,2], GF(5)) + [4 2 2 1 4] + [2 4 1 2 1] + [2 1 4 2 1] + [1 2 2 4 2] + [4 1 1 2 4] + """ + from sage.combinat.tableau import StandardTableaux + ST = StandardTableaux(la) + + def bilinear_form(p1, p2): + if len(p2) < len(p1): + p1, p2 = p2, p1 + return sum(c1 * p2.get(T1, 0) for T1, c1 in p1.items() if c1) + + gram_matrix = [[bilinear_form(polytabloid(T1), polytabloid(T2)) for T1 in ST] for T2 in ST] + return matrix(base_ring, gram_matrix) + + +def simple_module_rank(la, base_ring): + r""" + Return the rank of the simple `S_n`-module corresponding to the + partition ``la`` of size `n` over ``base_ring``. + + EXAMPLES:: + + sage: from sage.combinat.specht_module import simple_module_rank + sage: simple_module_rank([3,2,1,1], GF(3)) + 13 + """ + from sage.categories.fields import Fields + from sage.combinat.partition import Partition + if base_ring not in Fields(): + raise NotImplementedError("the base must be a field") + p = base_ring.characteristic() + la = Partition(la) + if not la.is_regular(p): + raise ValueError(f"the partition {la} is not {p}-regular") + return tabloid_gram_matrix(la, base_ring).rank() diff --git a/src/sage/combinat/symmetric_group_algebra.py b/src/sage/combinat/symmetric_group_algebra.py index 3884747f825..0334ce48707 100644 --- a/src/sage/combinat/symmetric_group_algebra.py +++ b/src/sage/combinat/symmetric_group_algebra.py @@ -1584,6 +1584,26 @@ 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_dimension(self, la): + r""" + Return the dimension of the simple module of ``self`` indexed by the + partition ``la``. + + EXAMPLES:: + + sage: SGA = SymmetricGroupAlgebra(GF(5), 6) + sage: SGA.simple_module_dimension(Partition([4,1,1])) + 10 + sage: SGA.simple_module_dimension(Partition([3,1,1])) + Traceback (most recent call last): + ... + ValueError: [3, 1, 1] is not a partition of 6 + """ + if sum(la) != self.n: + raise ValueError(f"{la} is not a partition of {self.n}") + from sage.combinat.specht_module import simple_module_rank + return simple_module_rank(la, self.base_ring()) + def jucys_murphy(self, k): r""" Return the Jucys-Murphy element `J_k` (also known as a diff --git a/src/sage/combinat/tableau.py b/src/sage/combinat/tableau.py index cdfaf7a2b5b..fb4a281a681 100644 --- a/src/sage/combinat/tableau.py +++ b/src/sage/combinat/tableau.py @@ -2992,7 +2992,16 @@ def column_stabilizer(self): sage: PermutationGroupElement([(1,4)]) in cs # optional - sage.groups True """ - return self.conjugate().row_stabilizer() + # 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]): + gens.append((val, self[ell-1][i])) + return PermutationGroup(gens) def height(self): """