Mélodie Lapointe (lapointe.melodie@courrier.uqam.ca) and Pauline Hubert (hubert.pauline@courrier.uqam.ca)

# Partitions¶

Recall that a **partition** \(\mu\) of \(n\), one writes
\(\mu\vdash n\) or \(n=|\mu|\), is a sequence of integers
\((\mu_0,\mu_1,\ldots, \mu_{k-1})\) (the \(m_i\)‘s are the
**parts** of \(\mu\)) with
\(\mu_0\geq \mu_1\geq\,\cdots\,\geq\mu_{k-1}>0\), and
\(n=\mu_0+\mu_1+\ldots+\mu_{k-1}\). The number \(\ell(\mu):=k\)
of parts of \(\mu\) is said to be its **length**. A partition
\(\mu\) may also be described as a **Ferrers diagram**, which is the
\(n\)-subset of \(\mathbb{N}\times \mathbb{N}\):

This set is also denoted \(\mu\), and its elements are the **cells**
of \(\mu\). The **conjuguate** of \(\mu\), is the partition
\(\mu'\) such that

Parts of \(\mu\) are the lengths of the **rows** of its diagram, and
parts of \(\mu'\) are the lengths of its **columns**.

For more, see https://en.wikipedia.org/wiki/Partition_(number_theory)

We mostly follow the notation conventions of Macdonald’s book:
*Symmetric Functions and Hall Polynomials*, Second Edition, Oxford
Mathematical Monographs, 1998.

Here are **a few preliminary declarations** just to make outputs nicer,
and diagrams to printout with the **French convention**. Partitions
parts are glued together, with parts of size larger that \(9\)
ending with a “dot” so that there is no confusion.

```
In [93]:
```

```
%display latex
def mystr(i):
if i<10:
return str(i)
else:
return ''.join([str(i),"."])
def compact(mu):
return (''.join(mystr(i) for i in mu))
Partition._latex_= compact
```

## Handling partitions in SAGE¶

Partition can be created/declared in SAGE the following way:

```
In [3]:
```

```
mu=Partition([10,10,2,2,1]); mu
```

```
Out[3]:
```

## Nice format versus normal one¶

with \(\mu\) here printed out in a nicer format than the usual:

```
In [4]:
```

```
print(Partition([10,10,2,2,1]))
```

```
[10, 10, 2, 2, 1]
```

## Listing partitions of \(n\)¶

One can also list all partitions of a given integer.

```
In [5]:
```

```
Partitions(4).list()
```

```
Out[5]:
```

## Number of partitions¶

Or simply calculate the number of partitions of \(n\).

(We underline that this function does not actually generate the partitions of \(n\) in order to count them; hence it is amazingly fast.)

```
In [6]:
```

```
Partitions(3000).cardinality()
```

```
Out[6]:
```

```
In [7]:
```

```
print(Partitions(100000).cardinality())
```

```
27493510569775696512677516320986352688173429315980054758203125984302147328114964173055050741660736621590157844774296248940493063070200461792764493033510116079342457190155718943509725312466108452006369558934464248716828789832182345009262853831404597021307130674510624419227311238999702284408609370935531629697851569569892196108480158600569421098519
```

## Partitions with constraints¶

One may add constraints on partitions; for instance, to get partitions of 5 of length 2:

```
In [8]:
```

```
p = Partitions(5,length=2)
p.list()
```

```
Out[8]:
```

or get all partitions of 6 with length between 3 and 5.

```
In [14]:
```

```
p = Partitions(6,min_length=3,max_length=5)
p.list()
```

```
Out[14]:
```

## Ferrers diagram¶

By default SAGE uses the English convention, but it has become the tradition in recent years to use the more natural (cartesian coordinates) French notation. Here is how to set this

```
In [33]:
```

```
Partitions.options.convention="french"
```

```
In [32]:
```

```
mu = Partition([8,5,5,5,4,3,3,2])
print(mu.ferrers_diagram())
```

```
********
*****
*****
*****
****
***
***
**
```

## Cells¶

The list of cells of \(m\) my be obtained as follows

```
In [34]:
```

```
mu.cells()
```

```
Out[34]:
```

and printed out in nice format as

```
In [36]:
```

```
map(compact,mu.cells())
```

```
Out[36]:
```

If one insists on using the English convention, rather than akwardly
reading this notebook “**… upside down, in a mirror …**” (as
Macdonald would say), one could globally switch back as follows

```
In [31]:
```

```
Partitions.options(convention='english')
print(mu.ferrers_diagram())
```

```
********
*****
*****
*****
****
***
***
**
```

## Partition containment¶

A partition \(\mu\) is said to be **included** in a partition
\(\lambda\) if \(\mu_i \leq \lambda_i\), for all \(i\). In
other words, the diagram of \(\mu\) is a subset of the diagram of
\(\lambda\). For example, one can list all partitions
\(\lambda\) of \(5\) such that the partition \([2,1]\) is
included in \(\lambda\).

```
In [26]:
```

```
p = Partitions(5,inner= [2,1])
p.list()
```

```
Out[26]:
```

Or all partitions of 5 included in the partition \([4,3,2,1]\).

```
In [27]:
```

```
p = Partitions(5,outer=[4,3,2,1])
p.list()
```

```
Out[27]:
```

The default (total) order on partitions is the lexicographic order.

```
In [29]:
```

```
mu = Partition([4,3,3])
nu = Partition([4,4,1])
mu < nu
```

```
Out[29]:
```

## Exercise:¶

```
In [83]:
```

```
q=var('q')
mu=[15,14,13,12,11,10,9,8,7,6,5,4,3,2,1]
sum(Partitions(i,outer=mu).cardinality()*q^i for i in range(20))
```

```
Out[83]:
```

# Young Tableaux¶

An \(A\)-valued **Young tableaux** of **shape** \(\mu\) is a
“filling” the cells of the Ferrers diagram of \(\mu\) with elements
of an ordered set \(A\). Hence it is a function
\(\tau:\mu\rightarrow A\). A tableau is said to **standard** if it
is bijective (hence \(A\) has cardinality equal to the number of
cells of \(\mu\)), and its entries on each row (and each column) are
stricly increasing from left to right (from bottom to top in french
convention). A tableau (not necessarily bijective) is said to be
**semistandard** if its entries are weakly increasing from left to right
on each row, and strictly increasing on each column. These object may be
constructed in the following way.

```
In [38]:
```

```
t = SemistandardTableau([[1,2,4],[3,3,6],[5,7],[8]])
t.pp()
print('')
s = StandardTableau([[1,2,4],[3,6],[5,7],[8]])
s.pp()
```

```
8
5 7
3 3 6
1 2 4
8
5 7
3 6
1 2 4
```

The function pp(\(\ \)) (“pp” stands for pretty print) gives a nicer display for Young tableaux. Observe that if you set options (like French vs English convention) for partitions, these will also apply to Young tableaux.

It is also possible to list all semistandard and standard Young tableaux of a given partition.

```
In [39]:
```

```
x = SemistandardTableaux([4,3,3,2,1])
print(x.cardinality())
y = StandardTableaux([4,3,3,2,1])
print(y.cardinality())
```

```
390780390
15015
```

The functions for partitions, such as display, options, cardinality, and list, may also be used on Young tableaux.

## Exercise:¶

Verify that the number of standard Young tableaux of shape :math:`[n,n]` is equal to the Catalan number for :math:`0 leq n leq 20`. (The function catalan_number(:math:`n`) returns the nth catalan number).

```
In [40]:
```

```
all(catalan_number(i)==StandardTableaux([i,i]).cardinality() for i in range(1,10))
```

```
Out[40]:
```

## Exercise:¶

Compute the sum of all monomials of degree 5 in three variables using partitions and standard tableaux.

```
In [41]:
```

```
var('x y z')
young_tableaux = []
monomials = []
for i in Partitions(5).list():
young_tableaux.extend(SemistandardTableaux(i,max_entry=3).list())
for j in young_tableaux:
k = reduce(operator.add,j)
monomials.append(x^k.count(1)*y^k.count(2)*z^k.count(3))
show(sum(monomials))
```

## Hook formula for the number of standard tableaux of shape \(\mu\)¶

The classical hook formula

```
In [47]:
```

```
def hook_formula(mu):
mu=Partition(mu)
return factorial(add(k for k in mu))/prod(mu.hook_length(i,j) for i,j in mu.cells())
```

```
In [48]:
```

```
hook_formula(Partition([4,3,1,1]))
```

```
Out[48]:
```

## Here are some functions on partitions often used in the theory of Macdonald polynomials¶

(Sometimes one may want a more functional notation for combinatorial calculations on diagrams.)

where \(a(c)\) et \(l(c)\) respectively denote the arm and the leg of a cell \(c\) in \(\mu\). We have

```
In [114]:
```

```
q,t=var('q,t')
def ell(mu):
mu=Partition(mu)
return mu.length()
def arm(c,mu):
mu=Partition(mu)
return mu.arm_length(c[0],c[1])
def leg(c,mu):
mu=Partition(mu)
return mu.leg_length(c[0],c[1])
def corner_cells(mu):
mu=Partition(mu)
return mu.corners()
def zee(mu):
mu=Partition(mu)
return mu.aut()
def n(mu): return add(i for i,j in mu.cells())
def B(mu):
return add(t^i*q^j for i,j in mu.cells())
def T(mu):
return prod(t^i*q^j for i,j in mu.cells())
def Pi(mu):
return prod(1-t^i*q^j for i,j in mu.cells() if [i,j]<>[0,0])
def epsilon(mu):
return prod((q^(arm(c,mu))-t^(1+leg(c,mu)))*(t^(leg(c,mu))-q^(1+arm(c,mu))) for c in mu.cells())
```

```
In [115]:
```

```
mu=Partition([4,3,3,1,1])
```

```
In [116]:
```

```
vector([n(mu),n(mu.conjugate())])== add(vector(c) for c in mu.cells())
```

```
Out[116]:
```

```
In [117]:
```

```
B(mu)
```

```
Out[117]:
```

```
In [118]:
```

```
Pi(mu)
```

```
Out[118]:
```

```
In [119]:
```

```
k=var('k')
factor(add(k^ell(mu)/zee(mu) for mu in Partitions(6)))
```

```
Out[119]:
```

```
In [120]:
```

```
factor(add((-k)^ell(mu)/zee(mu) for mu in Partitions(6)))
```

```
Out[120]:
```