Partition Shifting Algebras

This module contains families of operators that act on partitions or, more generally, integer sequences. In particular, this includes Young’s raising operators \(R_{ij}\), which act on integer sequences by adding \(1\) to the \(i\)-th entry and subtracting \(1\) to the \(j\)-th entry. A special case is acting on partitions.


  • Matthew Lancellotti, George H. Seelinger (2018): Initial version

class sage.combinat.partition_shifting_algebras.ShiftingOperatorAlgebra(base_ring=Univariate Polynomial Ring in t over Rational Field, prefix='S')

Bases: sage.combinat.free_module.CombinatorialFreeModule

An algebra of shifting operators.

Let \(R\) be a commutative ring. The algebra of shifting operators is isomorphic as an \(R\)-algebra to the Laurent polynomial ring \(R[x_1^\pm, x_2^\pm, x_3^\pm, \ldots]\). Moreover, the monomials of the shifting operator algebra act on any integer sequence \(\lambda = (\lambda_1, \lambda_2, \ldots, \lambda_{\ell})\) as follows. Let \(S\) be our algebra of shifting operators. Then, for any monomial \(s = x_1^{a_1}x_2^{a_2} \cdots x_r^{a_r} \in S\) where \(a_i \in \ZZ\) and \(r \geq \ell\), we get that \(s.\lambda = (\lambda_1 + a_1, \lambda_2 + a_2,\ldots,\lambda_r+a_r)\) where we pad \(\lambda\) with \(r-\ell\) zeros. In particular, we can recover Young’s raising operator, \(R_{ij}\), for \(i < j\), acting on partitions by having \(\frac{x_i}{x_j}\) act on a partition \(\lambda\).

One can extend the action of these shifting operators to a basis of symmetric functions, but at the expense of no longer actually having a well-defined operator. Formally, to extend the action of the shifting operators on a symmetric function basis \(B = \{b_{\lambda}\}_{\lambda}\), we define an \(R\)-module homomorphism \(\phi : R[x_1^\pm, x_2^\pm, \ldots] \to B\). Then we compute \(x_1^{a_1} \cdots x_r^{a_r}.b_\lambda\) by first computing \((x_1^{a_1} \cdots x_r^{a_r})x_1^{\lambda_1} \cdots x_\ell^{\lambda_\ell}\) and then applying \(\phi\) to the result. For examples of what this looks like with specific bases, see below.

This implementation is consistent with how many references work formally with raising operators. For instance, see exposition surrounding [BMPS2018] Equation (4.1).

We follow the following convention for creating elements: S(1, 0, -1, 2) is the shifting operator that raises the first part by \(1\), lowers the third part by \(1\), and raises the fourth part by \(2\).

In addition to acting on partitions (or any integer sequence), the shifting operators can also act on symmetric functions in a basis \(B\) when a conversion to \(B\) has been registered, preferably using build_and_register_conversion().

For a definition of raising operators, see [BMPS2018] Definition 2.1. See ij() to create operators using the notation in [BMPS2018].


  • base_ring – (default: QQ['t']) the base ring

  • prefix – (default: "S") the label for the shifting operators


sage: S = ShiftingOperatorAlgebra()

sage: elm = S[1, -1, 2]; elm
S(1, -1, 2)
sage: elm([5, 4])
[([6, 3, 2], 1)]

The shifting operator monomials can act on a complete homogeneous symmetric function or a Schur function:

sage: s = SymmetricFunctions(QQ['t']).s()
sage: h = SymmetricFunctions(QQ['t']).h()

sage: elm(s[5, 4])
s[6, 3, 2]
sage: elm(h[5, 4])
h[6, 3, 2]

sage: S[1, -1](s[5, 4])
s[6, 3]
sage: S[1, -1](h[5, 4])
h[6, 3]

In fact, we can extend this action by linearity:

sage: elm = (1 - S[1,-1]) * (1 - S[4])
sage: elm == S([]) - S([1, -1]) - S([4]) + S([5, -1])
sage: elm(s[2, 2, 1])
s[2, 2, 1] - s[3, 1, 1] - s[6, 2, 1] + s[7, 1, 1]

sage: elm = (1 - S[1,-1]) * (1 - S[0,1,-1])
sage: elm == 1 - S[0,1,-1] - S[1,-1] + S[1,0,-1]
sage: elm(s[2, 2, 1])
s[2, 2, 1] - s[3, 1, 1] + s[3, 2]

The algebra also comes equipped with homomorphisms to various symmetric function bases; these homomorphisms are how the action of S on the specific symmetric function bases is implemented:

sage: elm = S([3,1,2]); elm
S(3, 1, 2)
sage: h(elm)
h[3, 2, 1]
sage: s(elm)

However, not all homomorphisms are equivalent, so the action is basis dependent:

sage: elm = S([3,2,1]); elm
S(3, 2, 1)
sage: h(elm)
h[3, 2, 1]
sage: s(elm)
s[3, 2, 1]
sage: s(elm) == s(h(elm))

We can also use raising operators to implement the Jacobi-Trudi identity:

sage: op = (1-S[(1,-1)]) * (1-S[(1,0,-1)]) * (1-S[(0,1,-1)])
sage: s(op(h[3,2,1]))
s[3, 2, 1]
class Element

Bases: sage.modules.with_basis.indexed_element.IndexedFreeModuleElement

An element of a ShiftingOperatorAlgebra.

build_and_register_conversion(support_map, codomain)

Build a module homomorphism from a map sending integer sequences to codomain and registers the result into Sage’s conversion model.

The intended use is to define a morphism from self to a basis \(B\) of symmetric functions that will be used by ShiftingOperatorAlgebra to define the action of the operators on \(B\).


The actions on the complete homogeneous symmetric functions and on the Schur functions by morphisms are already registered.


Because ShiftingOperatorAlgebra inherits from UniqueRepresentation, once you register a conversion, this will apply to all instances of ShiftingOperatorAlgebra over the same base ring with the same prefix.


  • support_map – a map from integer sequences to codomain

  • codomain – the codomain of support_map, usually a basis of symmetric functions


sage: S = ShiftingOperatorAlgebra(QQ)
sage: sym = SymmetricFunctions(QQ)
sage: p = sym.p()
sage: zero_map = lambda part:
sage: S.build_and_register_conversion(zero_map, p)
sage: p(2*S([1,0,-1]) + S([2,1,0]) - 3*S([0,1,3]))
sage: op = S((1, -1))
sage: op(2*p[4,3] + 5*p[2,2] + 7*p[2]) ==

For a more illustrative example, we can implement a simple (but not mathematically justified!) conversion on the monomial basis:

sage: S = ShiftingOperatorAlgebra(QQ)
sage: sym = SymmetricFunctions(QQ)
sage: m = sym.m()
sage: def supp_map(gamma):
....:     gsort = sorted(gamma, reverse=True)
....:     return m(gsort) if gsort in Partitions() else
sage: S.build_and_register_conversion(supp_map, m)
sage: op = S.ij(0, 1)
sage: op(2*m[4,3] + 5*m[2,2] + 7*m[2]) == 2*m[5, 2] + 5*m[3, 1]
ij(i, j)

Return the raising operator \(R_{ij}\) as notated in [BMPS2018] Definition 2.1.

Shorthand element constructor that allows you to create raising operators using the familiar \(R_{ij}\) notation found in [BMPS2018] Definition 2.1, with the exception that indices here are 0-based, not 1-based.


Create the raising operator which raises part 0 and lowers part 2 (indices are 0-based):

sage: R = ShiftingOperatorAlgebra()
sage: R.ij(0, 2)
S(1, 0, -1)

Return the index of the basis element for \(1\).


sage: S = ShiftingOperatorAlgebra()
sage: S.one_basis()
product_on_basis(x, y)

Return the product of basis elements indexed by x and y.


sage: S = ShiftingOperatorAlgebra()
sage: S.product_on_basis((0, 5, 2), (3, 2, -2, 5))
S(3, 7, 0, 5)
sage: S.product_on_basis((1, -2, 0, 3, -6), (-1, 2, 2))
S(0, 0, 2, 3, -6)
sage: S.product_on_basis((1, -2, -2), (-1, 2, 2))
class sage.combinat.partition_shifting_algebras.ShiftingSequenceSpace

Bases: sage.misc.fast_methods.Singleton, sage.structure.parent.Parent

A helper for ShiftingOperatorAlgebra that contains all tuples with entries in \(\ZZ\) of finite support with no trailing \(0\)’s.


sage: from sage.combinat.partition_shifting_algebras import ShiftingSequenceSpace
sage: S = ShiftingSequenceSpace()
sage: (1, -1) in S
sage: (1, -1, 0, 9) in S
sage: [1, -1] in S
sage: (0.5, 1) in S

Verify that seq is a valid shifting sequence.

If it is not, raise a ValueError.


sage: from sage.combinat.partition_shifting_algebras import ShiftingSequenceSpace
sage: S = ShiftingSequenceSpace()
sage: S.check((1, -1))
sage: S.check((1, -1, 0, 9))
sage: S.check([1, -1])
Traceback (most recent call last):
ValueError: invalid index [1, -1]
sage: S.check((0.5, 1))
Traceback (most recent call last):
ValueError: invalid index (0.500000000000000, 1)