Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cartesian product in MATLAB

Here is the simplified version of the problem I have. Suppose I have a vector

p=[1 5 10] 

and another one

q=[.75 .85 .95]

And I want to come up with the following matrix:

res=[1, .75;
     1, .85;
     1, .95;
     5, .75;
     5, .85;
     5, .95;
    10, .75;
    10, .85;
    10, .95]

This is also known as the Cartesian Product. How can I do that?

like image 853
emper Avatar asked Mar 23 '12 04:03

emper


People also ask

How do you do a Cartesian product in Matlab?

CARTPROD Cartesian product of multiple sets. (The cartesian product of multiple input sets is a larger set containing every ordered combination of the input set elements. See example below.) X = CARTPROD(A,B,C,...) returns the cartesian product of the sets A,B,C, etc, where A,B,C, are numerical vectors.

How is Cartesian product defined?

In mathematics, the Cartesian Product of sets A and B is defined as the set of all ordered pairs (x, y) such that x belongs to A and y belongs to B. For example, if A = {1, 2} and B = {3, 4, 5}, then the Cartesian Product of A and B is {(1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5)}.

What is Cartesian product used for?

Most computers display images as a raster of points called pixels that can be addressed by their coordinates. These coordinates are ordered pairs and hence elements of a Cartesian product.

What is the product function in Matlab?

B = prod( A ) returns the product of the array elements of A . If A is a vector, then prod(A) returns the product of the elements. If A is a nonempty matrix, then prod(A) treats the columns of A as vectors and returns a row vector of the products of each column.


3 Answers

Here's one way:

[X,Y] = meshgrid(p,q);
result = [X(:) Y(:)];

The output is:

result =

    1.0000    0.7500
    1.0000    0.8500
    1.0000    0.9500
    5.0000    0.7500
    5.0000    0.8500
    5.0000    0.9500
   10.0000    0.7500
   10.0000    0.8500
   10.0000    0.9500
like image 112
nibot Avatar answered Oct 26 '22 07:10

nibot


A similar approach as the one described by @nibot can be found in matlab central file-exchange.

It generalizes the solution to any number of input sets. This would be a simplified version of the code:

function C = cartesian(varargin)
    args = varargin;
    n = nargin;

    [F{1:n}] = ndgrid(args{:});

    for i=n:-1:1
        G(:,i) = F{i}(:);
    end

    C = unique(G , 'rows');
end

For instance:

cartesian(['c','d','e'],[1,2],[50,70])

ans =

    99     1    50
    99     1    70
    99     2    50
    99     2    70
   100     1    50
   100     1    70
   100     2    50
   100     2    70
   101     1    50
   101     1    70
   101     2    50
   101     2    70
like image 37
jruizaranguren Avatar answered Oct 26 '22 05:10

jruizaranguren


Here's a function, cartesian_product, that can handle any type of input, including string arrays, and returns a table with column names that match the names of the input variables. Inputs that are not variables are given names like var1, var2, etc.

function tbl = cartesian_product(varargin)
    names = arrayfun(@inputname, 1:nargin, 'UniformOutput', false);
    
    for i = 1:nargin
        if isempty(names{i})
            names{i} = ['var' num2str(i)];
        end
    end
    
    rev_args = flip(varargin);
    
    [A{1:nargin}] = ndgrid(rev_args{:});

    B = cellfun(@(x) x(:), A, 'UniformOutput', false);
    C = flip(B);
    
    tbl = table(C{:}, 'VariableNames', names);
end
>> x = ["a" "b"];
>> y = 1:3;
>> z = 4:5;
>> cartesian_product(x, y, z)

ans =

  12×3 table

     x     y    z
    ___    _    _

    "a"    1    4
    "a"    1    5
    "a"    2    4
    "a"    2    5
    "a"    3    4
    "a"    3    5
    "b"    1    4
    "b"    1    5
    "b"    2    4
    "b"    2    5
    "b"    3    4
    "b"    3    5
>> cartesian_product(1:2, 3:4)

ans =

  4×2 table

    var1    var2
    ____    ____

     1       3  
     1       4  
     2       3  
     2       4
like image 26
Cameron Bieganek Avatar answered Oct 26 '22 07:10

Cameron Bieganek