Generate all possible combinations of elements of some vectors (Cartesian product)

I would like to generate all possible combinations of elements of a given number of vectors.

For example, for [1 2] , [1 2] and [4 5] I want to generate elements:

[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 do not know the number of vectors for which I need to calculate combinations. In this case, maybe 3, or maybe 10, and I need a generalization. Could you help me with this in MATLAB? Is there already a predefined function that can perform this task?

+31
matlab cartesian-product combinatorics
Nov 12 2018-10-12
source share
4 answers

Try ALLCOMB in FileExchange.

If you store vectors in an array of cells, you can run it as follows:

 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 
+16
Nov 12 2018-10-12
source share

Consider this solution using the NDGRID function:

 sets = {[1 2], [1 2], [4 5]}; [xyz] = 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 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 



Please note: if you prefer, you can sort the results:

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

In addition, the above code does not check for sets of duplicate values ​​(for example: {[1 1] [1 2] [4 5]} ). Add this line if you want:

 sets = cellfun(@unique, sets, 'UniformOutput',false); 
+46
Nov 12 '10 at
source share

These later answers provide two additional solutions, where the second solution (in my opinion) and the improvement of the Amro answer solution using ndgrid by using powerful MATLAB comma separated lists instead of cell arrays for high performance,

  • If you have a Neural Network Toolbox: use combvec
  • If you don’t have the tools, as it usually happens: below is another way to generalize the Cartesian product to any number of sets.

Like Amro in his answer, the syntax of comma-separated lists ( v{:} ) provides the inputs and outputs of ndgrid . The difference (fourth line) is that it avoids cellfun and cell2mat by applying comma-separated lists again, now as inputs to cat :

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

Using cat and reshape reduces the execution time by almost half. This approach was demonstrated in my answer to another question and more formally by Louis Mendo .

+11
Apr 24 '14 at 0:30
source share

we can also use combvec instruction in matlab

  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 this helps. Good luck.

0
Jan 13 '18 at 20:40
source share



All Articles