Stirling numbers of the second kind $S(n, k)$ count the number of ways to partition a set of $n$ elements into $k$ nonempty subsets. What if there were duplicate elements in the set? That is, the set is a multiset?
-
It would be good to add the link to the definition of Stirling numbers: http://en.wikipedia.org/wiki/Stirling_numbers_of_the_second_kind – Jan 09 '11 at 03:37
-
1The answer is likely to be somewhat complicated to express. For example, if the set consists of a single type of element, you get the partition numbers p_{n,k} : http://en.wikipedia.org/wiki/Partition_(number_theory) – Qiaochu Yuan Jan 09 '11 at 15:54
-
2I think [math] is a pretty useless tag in this site; I've deleted it and added [counting] – Arturo Magidin Jan 10 '11 at 21:54
5 Answers
There is no known formulation for a general multiset. However, a paper at JIS tackles the case where the element 1 occurs multiple times.
- 301
Here are two links to get you started:
Eulerian numbers of the second kind may be helpful (for counting ascents, descents, etc., though i think)
Additionally some more useful information may be found in Stanley's book
You divide the Stirling number by the possible permutations of identical elements as this is just changing order within the stars and bars example.
- 1
For those of you who want a faster program to compute this, I have written a Matlab program for this. Since the code does not require symbolic math, it is a lot faster than Marko Reidel's Maple code, especially when the multiset is large. In addition, the algorithm does not require the enumeration of the set partitions but instead it is based on a recurrence relation given in Gupta (1961), "On the Partition of J-partite Numbers," Proceedings of the National Institute of Sciences of India Part A 27, 579-587, but I have added quite a few improvements in my code. Here is the code.
%
% multipartr.m Date: 12/19/2024
% This Matlab function computes the number of
% set partitions for (n1*1, n2*2, ..., ns*s) with
% exactly r parts for r=1,...,n1+...+ns
% Input:
% n: a vector that indicates the frequencies of
% the multiset
% Output:
% y : a vector of the number of set partitions of
% the multiset that have exactly r parts for
% r=1,...,n1+...+ns
%
function y = multipartr(n)
s = length(n);
if s==1
F = ones(n,'uint64');
for j=2:n
F(:,j) = F(:,j-1);
F(j,j) = F(j,j)+1;
for i=j+1:n
F(i,j) = F(i,j)+F(i-j,j);
end
end
y = [1 diff(F(n,:))]';
return
end
n = sort(n,'descend');
n1 = n+1;
p = cumprod([1 n1(1:s-1)])';
pn = prod(n1);
%
% Create an index vector for \kappa's,
% where 0<=\kappa<=n. The index
% maps each \kappa to an element
% in the set of \kappa that is
% descending.
%
ind = zeros(pn,1);
kappa = zeros(1,s);
count = 1;
sk = 0;
for i=2:pn
j = 1;
while kappa(j)==n(j)
kappa(j) = 0;
sk = sk-n(j);
j = j+1;
end
kappa(j) = kappa(j)+1;
sk = sk+1;
if all(diff(kappa)<=0)
ind(i) = count;
count = count+sk;
else
i1 = sort(kappa,'descend')*p+1;
ind(i) = ind(i1);
end
end
A = zeros(count,1,'uint64');
A(1) = 1;
kappa = zeros(1,s);
sn = sum(n);
sk = 0; % sk = |\kappa|
% loop through \kappa with 0<\kappa<=n
% but only for those kappa's that are
% descending.
while sk<sn
j = 1;
while kappa(j)==n(j)
j = j+1;
end
kappa(j) = kappa(j)+1;
if j==1
sk = sk+1;
else
kappa(1:j-1) = kappa(j);
sk = sum(kappa);
end
ind1 = kappa*p+1;
indc = ind(ind1);
y1 = zeros(sk,1,'uint64');
y1(1) = 1;
nu = zeros(1,s);
snu = 0;
ind2 = 0; % ind2 = nu*p
% loop through \nu with 0<\nu<\kappa
for ii=1:prod(kappa+1)-2
j1 = 1;
while nu(j1)==kappa(j1)
nu(j1) = 0;
snu = snu-kappa(j1);
ind2 = ind2-kappa(j1)*p(j1);
j1 = j1+1;
end
nu(j1) = nu(j1)+1;
snu = snu+1;
ind2 = ind2+p(j1);
sk2 = sk;
for r=1:min(floor(kappa./nu))
sk2 = sk2-snu;
if sk2>0
c1 = ind(ind1-r*ind2)-r;
for i=r+1:r+sk2
y1(i) = y1(i)+A(c1+i);
end
else
y1(r) = y1(r)+1;
end
end
end
for i=1:sk
A(indc+i) = y1(i)/i;
end
end
y = A(end-sn+1:end);
If you do multipartr([2 2 3 3]), you get
1
71
536
1204
1223
704
257
63
10
1
Even for something as large as multipartr([12 12 13 13]), it takes 1.1 seconds to do on my Ryzen 5950x. If you are only interested in obtaining the total number of set partitions, i.e., sum(multipartr([12 12 13 13])), it can be done in 0.1 second. E-mail me if you are interested in having this code.
- 23