mrish
mrish

Reputation: 29

Dynamic Matrix Columns combinations

I would like to find all possible combinations of a matrix columns, with each column contributing a value, in each iteration of a loop. The matrix size changes in each iteration. For example:

A = [1 2 3 
     4 5 6
     7 8 9].

should produce:

1 2 3
1 2 6
1 5 3

etc. but should not produce:

1 4 2

for example.

My problems: When I insert the matrix to the combvec function nothing happens. The function accepts vectors - and since I do it with a different matrix size in each iteration of a loop I can't write it manually. ndgrid also requires vectors - and since I need to choose a combination index in another variable, I'm not clear how this happens. I don't have combination function in my Matlab version. Is there a way to define vectors dynamically in a loop? Any idea on to how overcome this? Do I need to write a combination function myself?

I've tried used combvec with a matrix - it returns the matrix itself without combinations.

Upvotes: 2

Views: 78

Answers (2)

ThomasIsCoding
ThomasIsCoding

Reputation: 101335

combinations + num2cell

I think you can use num2cell + combinations

x = num2cell(A,1);
combinations(x{:})

which gives a table like below

ans =

  27×3 table

    Var1    Var2    Var3
    ____    ____    ____

     1       2       3  
     1       2       6  
     1       2       9  
     1       5       3  
     1       5       6  
     1       5       9  
     1       8       3  
     1       8       6  
     1       8       9  
     4       2       3  
     4       2       6  
     4       2       9  
     4       5       3  
     4       5       6  
     4       5       9  
     4       8       3  
     4       8       6  
     4       8       9  
     7       2       3  
     7       2       6  
     7       2       9  
     7       5       3  
     7       5       6  
     7       5       9  
     7       8       3  
     7       8       6  
     7       8       9 

Recursion For Grids (Custom Functions)

If you are interested in customized coding, you can write a recursion with combvec like below

function out = expandgrid(mat)
if iscolumn(mat)
    out = mat.';
else
    out = combvec(expandgrid(mat(:,1:end-1)), mat(:,end).');
end
end

and then run transpose(expandgrid(A)), which gives


     1     2     3
     4     2     3
     7     2     3
     1     5     3
     4     5     3
     7     5     3
     1     8     3
     4     8     3
     7     8     3
     1     2     6
     4     2     6
     7     2     6
     1     5     6
     4     5     6
     7     5     6
     1     8     6
     4     8     6
     7     8     6
     1     2     9
     4     2     9
     7     2     9
     1     5     9
     4     5     9
     7     5     9
     1     8     9
     4     8     9
     7     8     9

Or, you can use repmat + repelem like below to define the recursion

function out = expandgrid(mat)
nr = size(mat,1);
if iscolumn(mat)
    out = mat;
else
    p = repmat(expandgrid(mat(:,1:end-1)), nr, 1);
    q = repelem(mat(:,end), length(p)/nr);
    out = [p, q];
end
end

and expandgrid(A) can yield

     1     2     3
     4     2     3
     7     2     3
     1     5     3
     4     5     3
     7     5     3
     1     8     3
     4     8     3
     7     8     3
     1     2     6
     4     2     6
     7     2     6
     1     5     6
     4     5     6
     7     5     6
     1     8     6
     4     8     6
     7     8     6
     1     2     9
     4     2     9
     7     2     9
     1     5     9
     4     5     9
     7     5     9
     1     8     9
     4     8     9
     7     8     9

Upvotes: 1

Wolfie
Wolfie

Reputation: 30046

combvec accepts vectors, so split your matrix into a cell of vectors (one per column)

v = arrayfun( @(x) A(:,x).', (1:size(A,2)), 'uni', 0 );

[Edit: equivalent simpler suggestion from Luis' comment v = num2cell(A.', 2);]

Then pass all of these vectors as individual inputs to combvec:

c = combvec( v{:} ).';

Be wary if this is "dynamic" as A wouldn't have to be much larger before your combinations output is significantly larger and your program will slow down significantly (or run out of RAM).

Output:

c =

     1     2     3
     4     2     3
     7     2     3
     1     5     3
     4     5     3
     7     5     3
     1     8     3
     4     8     3
     7     8     3
     1     2     6
     4     2     6
     7     2     6
     1     5     6
     4     5     6
     7     5     6
     1     8     6
     4     8     6
     7     8     6
     1     2     9
     4     2     9
     7     2     9
     1     5     9
     4     5     9
     7     5     9
     1     8     9
     4     8     9
     7     8     9

Upvotes: 4

Related Questions