Skip to content

Commit bd88b64

Browse files
committed
Merge pull request #6 from jiahao/young
Provides some functions for working with Young diagrams.
2 parents 4fb872b + fd78850 commit bd88b64

File tree

4 files changed

+188
-0
lines changed

4 files changed

+188
-0
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,15 @@ This library provides the following functions:
1919
- `multinomial(k...)`: receives a tuple of `k_1, ..., k_n` and calculates the multinomial coefficient `(n k)`, where `n = sum(k)`; returns a `BigInt` only if given a `BigInt`;
2020
- `primorial(n)`: returns the product of all positive prime numbers <= n; always returns a `BigInt`;
2121
- `stirlings1(n, k)`: the signed `(n,k)`-th Stirling number of the first kind; returns a `BigInt` only if given a `BigInt`.
22+
23+
24+
Young diagrams
25+
--------------
26+
Limited support for working with Young diagrams is provided.
27+
28+
- `partitionsequence(a)`: computes partition sequence for an integer partition `a`
29+
- `x = a \ b` creates the skew diagram for partitions (tuples) `a`, `b`
30+
- `isrimhook(x)`: checks if skew diagram `x` is a rim hook
31+
- `leglength(x)`: computes leg length of rim hook `x`
32+
- `character(a, b)`: computes character the partition `b` in the `a`th irrep of Sn
33+

src/Catalan.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ export bell,
1717
stirlings1,
1818
subfactorial
1919

20+
include("youngdiagrams.jl")
21+
2022
# Returns the n-th Bell number
2123
function bell(bn::Integer)
2224
if bn < 0

src/youngdiagrams.jl

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
################################################################################
2+
# Young diagrams, partitions of unity and characters of the symmetric group Sn #
3+
################################################################################
4+
5+
typealias partition Vector{Int64}
6+
typealias youngdiagram Array{Int64,2}
7+
typealias skewdiagram (partition, partition)
8+
9+
export partition,
10+
youngdiagram, #represents shape of Young diagram
11+
skewdiagram, #skew diagrams
12+
partitionsequence,
13+
isrimhook, #Check if skew diagram is rim hook
14+
leglength,
15+
character #Computes character of irrep of Sn
16+
17+
import Base.\
18+
19+
#################
20+
# Skew diagrams #
21+
#################
22+
23+
#This uses a very simple internal representation for skew diagrams
24+
\::partition, μ::partition) = Makeskewdiagram(λ, μ)
25+
function Makeskewdiagram::partition, μ::partition)
26+
m, n = length(λ), length(μ)
27+
if n>m error("Cannot construct skew diagram") end
28+
(λ, μ)
29+
end
30+
31+
#Checks if skew diagram is a rim hook
32+
isrimhook::partition, μ::partition)=isrimhook\ μ)
33+
function isrimhook::skewdiagram)
34+
λ, μ = ξ
35+
m, n = length(λ), length(μ)
36+
if n>m error("Cannot construct skew diagram") end
37+
#Construct matrix representation of diagram
38+
#XXX This is a horribly inefficient way of checking condition 1!
39+
l = max(λ)
40+
youngdiagram=zeros(Int64, m, l)
41+
for i=1:n
42+
youngdiagram[i, μ[i]+1:λ[i]]=1
43+
end
44+
for i=n+1:m
45+
youngdiagram[i, 1:λ[i]]=1
46+
end
47+
#Condition 1. Must be edgewise connected
48+
youngdiagramList=[]
49+
for i=1:m
50+
for j=1:l
51+
if youngdiagram[i, j]==1 youngdiagramList = [youngdiagramList; (i, j)] end
52+
end
53+
end
54+
for k=1:length(youngdiagramList)
55+
i, j = youngdiagramList[k]
56+
numNeighbors = 0
57+
for kp=1:length(youngdiagramList)
58+
ip,jp= youngdiagramList[kp]
59+
if abs(i-ip) + abs(j-jp) == 1 numNeighbors += 1 end
60+
end
61+
if numNeighbors == 0 return false end #Found a cell with no adjacent neighbors
62+
end
63+
#Condition 2. Must not contain 2x2 square of cells
64+
for i=1:m-1
65+
for j=1:l-1
66+
if youngdiagram[i, j]== 0 continue end
67+
if youngdiagram[i, j+1] == youngdiagram[i+1, j] == youngdiagram[i+1, j+1] == 1
68+
return false
69+
end
70+
end
71+
end
72+
return true
73+
end
74+
75+
76+
#Strictly speaking, defined for rim hook only, but here we define it for all skew diagrams
77+
leglength::partition, μ::partition)=leglength((λ \ μ))
78+
function leglength::skewdiagram)
79+
λ, μ = ξ
80+
m, n = length(λ), length(μ)
81+
#Construct matrix representation of diagram
82+
l = max(λ)
83+
youngdiagram=zeros(Int64, m, l)
84+
for i=1:n
85+
youngdiagram[i, μ[i]+1:λ[i]]=1
86+
end
87+
for i=n+1:m
88+
youngdiagram[i, 1:λ[i]]=1
89+
end
90+
for i=m:-1:1
91+
if any([x==1 for x in youngdiagram[i,:]]) return i-1 end
92+
end
93+
return -1 #If entire matrix is empty
94+
end
95+
96+
97+
#######################
98+
# partition sequences #
99+
#######################
100+
101+
#Computes essential part of the partition sequence of lambda
102+
function partitionsequence(lambda::partition)
103+
Λ▔ = Int64[]
104+
λ = [lambda; 0]
105+
m = length(lambda)
106+
for i=m:-1:1
107+
for k=1:(λ[i]-λ[i+1])
108+
Λ▔ = [Λ▔; 1]
109+
end
110+
Λ▔ = [Λ▔ ; 0]
111+
end
112+
Λ▔
113+
end
114+
115+
#This takes two elements of a partition sequence, with a to the left of b
116+
isrimhook(a::Int64, b::Int64) = (a==1) && (b==0)
117+
118+
119+
#############################
120+
# Character of irreps of Sn #
121+
#############################
122+
123+
#Computes recursively using the Murnaghan-Nakayama rule.
124+
function MN1inner(R::Vector{Int64}, T::Dict, μ::partition, t::Integer)
125+
s=length(R)
126+
χ::Integer=1
127+
if t<=length(μ)
128+
χ, σ::Integer = 0, 1
129+
for j=1:μ[t]-1
130+
if R[j]==0 σ=-σ end
131+
end
132+
for i=1:s-μ[t]
133+
if R[i] != R[i+μ[t]-1] σ=-σ end
134+
if isrimhook(R[i], R[i+μ[t]])
135+
R[i], R[i+μ[t]] = R[i+μ[t]], R[i]
136+
rhohat = R[i:i+μ[t]]
137+
if !has(T, rhohat) #Cache result in lookup table
138+
T[rhohat] = MN1inner(R, T, μ, t+1)
139+
end
140+
χ += σ * T[rhohat]
141+
R[i], R[i+μ[t]] = R[i+μ[t]], R[i]
142+
end
143+
end
144+
end
145+
χ
146+
end
147+
148+
#Computes character $χ^λ(μ)$ of the partition μ in the λth irrep of the
149+
#symmetric group $S_n$
150+
#
151+
#Implements the Murnaghan-Nakayama algorithm as described in:
152+
# Dan Bernstein,
153+
# "The computational complexity of rules for the character table of Sn",
154+
# Journal of Symbolic Computation, vol. 37 iss. 6 (2004), pp 727-748.
155+
# doi:10.1016/j.jsc.2003.11.001
156+
function character::partition, μ::partition)
157+
T = {()=>0} #Sparse array implemented as dict
158+
Λ▔ = partitionsequence(λ)
159+
MN1inner(Λ▔, T, μ, 1)
160+
end
161+
162+

test/youngdiagrams.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using Catalan
2+
using Base.Test
3+
4+
@test ([5,4,2,2]\[2,1]) == ([5, 4, 2, 2],[2, 1])
5+
@test isrimhook([4,3,2], [2,2,2])
6+
@test !isrimhook([4,3,2], [2,2,1])
7+
@test !isrimhook([4,3,2], [1,1])
8+
λ = [5,4,2,1]
9+
@test partitionsequence(λ) == [1, 0, 1, 0, 1, 1, 0, 1, 0]
10+
@test character(λ, [4,3,2,2,1]) == 0
11+
@test character([1], [1]) == 1
12+

0 commit comments

Comments
 (0)