Matlab 查找超过给定值的数组元素之和?

Matlab 查找超过给定值的数组元素之和?,matlab,matrix,subset,vectorization,combinatorics,Matlab,Matrix,Subset,Vectorization,Combinatorics,我试图利用MATLAB中的矢量化实现这一点,但我可能不得不求助于来实现循环。我真的不想那样做!学习算法的时间到了 给定此(11×3)阵列: 我想找到数组中11个元素的所有3^11=177147个可能的和,其中11个元素中的每一个都来自不同的行。然后,我想将超过阈值16.0的和以及构成这些和的11个元素存储在一个(12×-?)数组中 有什么办法让我开始吗?谢谢你的帮助。我认为你的运气不会比使用for循环好。可以使用Matlab函数生成所有3^11个组合,并将其用作索引,但这样会消耗大量内存 代码也

我试图利用MATLAB中的矢量化实现这一点,但我可能不得不求助于
来实现
循环。我真的不想那样做!学习算法的时间到了

给定此(11×3)阵列:

我想找到数组中11个元素的所有3^11=177147个可能的和,其中11个元素中的每一个都来自不同的行。然后,我想将超过阈值16.0的和以及构成这些和的11个元素存储在一个(12×-?)数组中


有什么办法让我开始吗?谢谢你的帮助。

我认为你的运气不会比使用for循环好。可以使用Matlab函数生成所有3^11个组合,并将其用作索引,但这样会消耗大量内存

代码也很难阅读


然而,最新版本的Matlab在wrt for循环中的表现并没有那么糟糕,因为它们对代码进行了JIT。在它被解释之前,或者JIT被用于特定的目的。因此,您不希望在Matlab中重新实现矩阵例程,但对于像这样的简单代码,它应该表现良好。

以下是如何以矢量化的方式实现它:

TR = 16;

sets = num2cell(single(x),2);

c = cell(1, numel(sets));
[c{:}] = ndgrid( sets{:} );
cartProd = cell2mat( cellfun(@(v)v(:), c, 'UniformOutput',false) );

validRows = cartProd(sum(cartProd,2) > TR,:); % output is [353x11]
注意我如何使用
single
来节省空间并使计算稍微快一点

上述解决方案是对答案的改编


经过进一步的思考,我想我已经想出了一种既能更快又能更有效地利用内存的方法。我们通过索引
x
,然后对索引执行前面的过程来实现这一点。你可能会问,为什么这样更好?这是因为我们可以将索引存储为
uint8
,这比
double
甚至
single
消耗的内存要少得多。我们还可以保持
x
的完整
double
精度。因此:

function validRows = q42933114(x,thresh)
%% Input handling
if nargin < 2
  thresh = 16;
end
if nargin < 1
  x = [...
    4.9000   -0.1000   -5.1000
    4.6000   -0.4000   -5.4000
    3.0000   -2.0000   -7.0000
    2.9000   -2.1000   -7.1000
    2.9000   -2.1000   -7.1000
    2.9000   -2.1000   -7.1000
    2.8000   -2.2000   -7.2000
    2.7000   -2.3000   -7.3000
    2.7000   -2.3000   -7.3000
    2.2000   -2.8000   -7.8000
    1.8000   -3.2000   -8.2000
  ];
end

I = reshape(uint8(1:numel(x)),size(x));

sets = num2cell(I,2);

c = cell(1, numel(sets));
[c{:}] = ndgrid( sets{:} );
cartProd = cell2mat( cellfun(@(v)v(:), c, 'UniformOutput',false) );
validRows = x(cartProd(sum(x(cartProd),2) > thresh,:));
方法2(新的):

我们看到内存消耗确实比预期的要小(大约4倍)

运行时比较:
方法1--0.0110
方法2--0.0186

这里我们看到第二种方法实际上有点慢。当分析这一点时,我们发现原因是相对昂贵的
x(…)

我是这样做的。显然,变量名还有改进的余地

请注意,
353
匹配行与@Dev iL的答案一致

p = 11;
[a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11] = ...
    ndgrid(x(1,:),x(2,:),x(3,:),x(4,:),x(5,:),x(6,:),x(7,:),x(8,:),x(9,:),x(10,:),x(11,:));
a = a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11;
y = spalloc(p+1,3^p,(p+1)*3^p);
for i = 1:3^p
    if a(i) >= 16.1
        y(:,i) = [a1(i),a2(i),a3(i),a4(i),a5(i),a6(i),a7(i),a8(i),a9(i),a10(i),a11(i),a(i)];
    end
end
nnz(y(p+1,:)); % 353 rows matching the criteria

这应该是一个评论。啊,谢谢!我也在研究一个解决方案,我刚刚得到了它,尽管效率要低得多。最后,我使用了
ndgrid
spalloc
@abscissa,您可能希望将您的解决方案作为另一个答案发布。
>> whos
  Name                Size              Bytes  Class     Attributes

  c                   1x11            7795700  cell                
  cartProd       177147x11            7794468  single              
  sets               11x1                1364  cell                
  validRows         353x11              15532  single              
>> whos
  Name                Size              Bytes  Class     Attributes

  c                   1x11            1949849  cell                
  cartProd       177147x11            1948617  uint8               
  sets               11x1                1265  cell                
  validRows         353x11              31064  double              
p = 11;
[a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11] = ...
    ndgrid(x(1,:),x(2,:),x(3,:),x(4,:),x(5,:),x(6,:),x(7,:),x(8,:),x(9,:),x(10,:),x(11,:));
a = a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11;
y = spalloc(p+1,3^p,(p+1)*3^p);
for i = 1:3^p
    if a(i) >= 16.1
        y(:,i) = [a1(i),a2(i),a3(i),a4(i),a5(i),a6(i),a7(i),a8(i),a9(i),a10(i),a11(i),a(i)];
    end
end
nnz(y(p+1,:)); % 353 rows matching the criteria