简体   繁体   English

生成某些向量元素的所有可能组合(笛卡尔积)

[英]Generate all possible combinations of the elements of some vectors (Cartesian product)

I would like to generate all the possible combinations of the elements of a given number of vectors.我想生成给定数量向量的元素的所有可能组合。

For example, for [1 2] , [1 2] and [4 5] I want to generate the elements:例如,对于[1 2][1 2][4 5]我想生成元素:

[1 1 4; 1 1 5; 1 2 4; 1 2 5; 2 1 4; 2 1 5; 2 2 4; 2 2 5]

The problem is that I don't know the number of vectors for which I need to calculate the combinations.问题是我不知道需要计算组合的向量数量。 There might be 3 as in this case, or there may be 10, and I need a generalization .在这种情况下可能有 3 个,或者可能有 10 个,我需要一个概括 Can you please help me to this in MATLAB?你能在 MATLAB 中帮我解决这个问题吗? Is there already a predefined function that can do this task?是否已经有预定义的 function 可以执行此任务?

Consider this solution using the NDGRID function: 考虑使用NDGRID函数的此解决方案:

sets = {[1 2], [1 2], [4 5]};
[x y z] = ndgrid(sets{:});
cartProd = [x(:) y(:) z(:)];

cartProd =
     1     1     4
     2     1     4
     1     2     4
     2     2     4
     1     1     5
     2     1     5
     1     2     5
     2     2     5

Or if you want a general solution for any number of sets (without having to create the variables manually), use this function definition: 或者,如果您想为任意数量的集合提供通用解决方案(而不必手动创建变量),请使用以下函数定义:

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

Note that if you prefer, you can sort the results: 请注意,如果您愿意,可以对结果进行排序:

cartProd = sortrows(cartProd, 1:numel(sets));

Also, the code above does not check if the sets have no duplicate values (ex: {[1 1] [1 2] [4 5]} ). 另外,上面的代码不检查集合是否没有重复值(例如: {[1 1] [1 2] [4 5]} )。 Add this one line if you want to: 如果您要添加这一行:

sets = cellfun(@unique, sets, 'UniformOutput',false);

Try ALLCOMB function at FileExchange. FileExchange尝试ALLCOMB函数。

If you store you vectors in a cell array, you can run it like this: 如果将向量存储在单元格数组中,则可以这样运行它:

a = {[1 2], [1 2], [4 5]};
allcomb(a{:})
ans =

     1     1     4
     1     1     5
     1     2     4
     1     2     5
     2     1     4
     2     1     5
     2     2     4
     2     2     5

This late answers provides two additional solutions, where the second is the solution (in my opinion) and an improvement on Amro's answer solution with ndgrid by applying MATLAB's powerful comma-separated lists instead of cell arrays for high performance, 最新的答案提供了另外两个解决方案,其中第二个是解决方案 (我认为),并且通过应用MATLAB强大的逗号分隔列表而不是单元格数组来提高Amro对ndgrid的答案解决方案的性能,

  1. If you have the Neural Network Toolbox: use combvec 如果您有神经网络工具箱:请使用combvec
  2. If you do not have the toolbox, as is usually the case: below is another way to generalize the Cartesian product for any number of sets. 如果没有工具箱(通常是这种情况):下面是对任意数量的集合进行笛卡尔乘积推广的另一种方法。

Just as Amro did in his answer, the comma-separated lists syntax ( v{:} ) supplies both the inputs and outputs of ndgrid . 就像Amro在回答中所做的那样,逗号分隔的列表语法( v{:} )提供ndgrid的输入和输出。 The difference (fourth line) is that it avoids cellfun and cell2mat by applying comma-separated lists, again, now as the inputs to cat : 区别(第四行)是,它再次应用逗号分隔的列表作为cat的输入,从而避免了cellfuncell2mat

N = numel(a);
v = cell(N,1);
[v{:}] = ndgrid(a{:});
res = reshape(cat(N+1,v{:}),[],N);

The use of cat and reshape cuts execution time almost in half. 使用catreshape将执行时间减少近一半。 This approach was demonstrated in my answer to an different question , and more formally by Luis Mendo . 路易斯·门多(Luis Mendo)我对另一个问题的回答中 更详细地说明了这种方法。

we can also use the 'combvec' instruction in matlab 我们也可以在matlab中使用'combvec'指令

    no_inp=3 % number of inputs we want...in this case we have 3 inputs                  
    a=[1 2 3]
    b=[1 2 3]
    c=[1 2 3]

    pre_final=combvec(c,b,a)';
    final=zeros(size(pre_final));

    for i=1:no_inp
    final(:,i)=pre_final(:,no_inp-i+1);
    end
    final 

Hope it helps. 希望能帮助到你。 Good luck. 祝好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM