【问题标题】:specific tuples generation and counting (matlab)特定元组的生成和计数(matlab)
【发布时间】:2013-03-09 05:33:27
【问题描述】:

我需要生成(我更喜欢 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

提前感谢您的帮助。

【问题讨论】:

    标签: matlab tuples combinatorics multiple-conditions


    【解决方案1】:

    这是更好的算法,由 Bruno Luong(杰出的 MATLAB 程序员)创建:

    function [t, m, v] = tupmul(n, w)
    v = tmr(length(w), n, w);
    t = sort(v,2);
    [t,~,J] = unique(t,'rows');
    m = accumarray(J(:),1);
    end % tupmul
    
    function v = tmr(p, n, w, head)
    if p==1
        if n <= w(end)
            v = n;
        else
            v = zeros(0,1);
        end
    else
        jmax = min(n,w(end-p+1));
        v = cell2mat(arrayfun(@(j) tmr(p-1, n-j, w, j), (0:jmax)', ...
            'UniformOutput', false));
    end
    
    if nargin>=4 % add a head column
        v = [head+zeros(size(v,1),1,class(head)) v];
    end
    
    end %tmr
    

    【讨论】:

      【解决方案2】:

      非常粗糙(极其无效)的解决方案。 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
      

      【讨论】:

      • 显然我的unique / perms 方法对你有帮助吗? :-)
      • 是的!但是可以更有效地计算多重性...查看下一个答案
      • [tup mul] = tupmul(8,[1 1 2 2 2]) 产生错误结果,应该是 mul = 1
      • 是的......真相的苦葡萄:)
      猜你喜欢
      • 1970-01-01
      • 2015-05-28
      • 2019-10-01
      • 1970-01-01
      • 2021-04-21
      • 2023-01-24
      • 1970-01-01
      • 2018-02-03
      • 1970-01-01
      相关资源
      最近更新 更多