特定元组生成和计数(matlab)

我需要生成(我更喜欢MATLAB)所有“唯一”整数元组k =(k_1,k_2,…,k_r)和

其相应的多重性,满足两个附加条件:

1. sum(k) = n
2. 0<=k_i<=w_i, where vector w = (w_1,w_2, ..., w_r) contains predefined limits w_i.

“唯一”元组意味着它包含唯一的无序元素集
(k_1,k_2,…,k_r)

[t,m] = func(n,w)
t ... matrix of tuples, m .. vector of tuples multiplicities

典型的问题维度是:

n ~ 30, n <= sum(w) <= n+10, 5 <= r <= n

(我希望存在任何多项式时间算法!!!)

 Example:

n = 8, w = (2,2,2,2,2), r = length(w) 

[t,m] = func(n,w)

t = 

2 2 2 2 0 

2 2 2 1 1

m = 

5

10

在这种情况下,只存在两个“唯一”元组:

(2,2,2,2,0)具有多重性5

有5个“相同”的元组具有相同的元素集

 0     2     2     2     2

 2     0     2     2     2

 2     2     0     2     2

 2     2     2     0     2

 2     2     2     2     0

(2,2,2,1,1)具有多重性10

有10个“相同”的元组具有相同的元素集

 1     1     2     2     2

 1     2     1     2     2

 1     2     2     1     2

 1     2     2     2     1

 2     1     1     2     2

 2     1     2     1     2

 2     1     2     2     1

 2     2     1     1     2

 2     2     1     2     1

 2     2     2     1     1

在此先感谢您的帮助.

最佳答案 非常粗糙(极其无效)的解决方案. FOR循环超过2 ^ nvec-1(nvec = r * maxw)测试样本和变量res的存储是非常可怕的事情!

该解决方案基于以下question.

有没有更有效的方法?

function [tup,mul] = tupmul(n,w)
r = length(w);
maxw = max(w);
w = repmat(w,1,maxw+1);
vec = 0:maxw;
vec = repmat(vec',1,r);
vec = reshape(vec',1,r*(maxw+1));
nvec = length(vec);
res = [];
for i = 1:(2^nvec - 1)
    ndx = dec2bin(i,nvec) == '1';
    if sum(vec(ndx)) == n && all(vec(ndx)<=w(ndx)) && length(vec(ndx))==r
        res = [res; vec(ndx)];
    end
end
tup = unique(res,'rows');
ntup = size(tup,1);
mul = zeros(ntup,1);
for i=1:ntup
    mul(i) = size(unique(perms(tup(i,:)),'rows'),1);
end
end

例:

> [tup mul] = tupmul(8,[2 2 2 2 2])

tup =

     0 2 2 2 2
     1 1 2 2 2


mul =

     5
    10 

或者相同的情况,但前两个位置的限制已经改变:

>> [tup mul] = tupmul(8,[1 1 2 2 2])

tup =

     1     1     2     2     2


mul =

    10
点赞