-1

Here is what i want to do:

I have 4 inputs x1, x2, x3, x4

They each have a range of possible values, f.e

x1={1,2}

x2=x3=x4={1,2,3}

These values x1, x2, x3, x4 may be known, but they can also be unknow (input=0). I want to generate a matrix with all possible combinations.

So for example: the input (0,0,2,3) means, that x1 and x2 are unknown and x3 and x4 are known. Since x1 has 2 possibilities and x2 has 3 possibilities I need 2*3=6 combinations, where x3 and x4 are fixed:

1 1 2 3
1 2 2 3
1 3 2 3
2 1 2 3
2 2 2 3
2 3 2 3

How do i archieve that? Normally i would do a couple nested for loops, but that doenst work, since i dont know which variables are known and which one are not. On the other hand perm() doenst really help either.

Luis Mendo
  • 110,752
  • 13
  • 76
  • 147

3 Answers3

0

You can pre-generate all of the possible combinations of values for [x1 x2 x3 x4] and store it in the variable, for example comb.

From there on:

inputs = [x1 x2 x3 x4];   % Put your inputs in a vector
fixed  = ~(inputs == 0);  % Logical vector for where inputs is not zero

select = ismember(combs(:,fixed),inputs(fixed),'rows') % find where the values correspond

yourMatrix = combs(select,:); % Get your results
Tamás Szabó
  • 733
  • 6
  • 9
0

Try this (this should be generalisable):

% This is your input
ranges = {[1, 2], [1, 2, 3], [1, 2, 3], [1, 2, 3]};
input_v = [0, 0, 2, 3];

% initialise a cell to hold vectors to be combined
combine_us = cell(size(ranges));

for ii = 1:length(input_v)
    % this tests for 0. If your arrays can contain 0, use NaN instead
    if input_v(ii) == 0
        combine_us{ii} = ranges{ii};
    else
        combine_us{ii} = input_v(ii);
    end
end
% calculate the numbers of combinations added with every input
n_combinations = [1 cumprod(cellfun(@numel, combine_us))];
% initialize output matrix
out_v = zeros(n_combinations(end), length(input_v));
% set the output values, cycling so that each combination will be obtained
for ii = 1:length(input_v)
    for jj = 1:n_combinations(end)
        out_v(jj, ii) = combine_us{ii}(mod(ceil(jj / n_combinations(ii)) - 1, length(combine_us{ii} )) + 1);
    end
end
zeeMonkeez
  • 5,057
  • 3
  • 33
  • 56
0

I'm assuming your inputs are numeric vectors, rather than cell arrays of numbers. If they are really cell arrays of numbers, you can convert to numeric vectors with x1 = [x1{:}]; etc.

You can proceed as follows:

  1. Build a cell array such that each cell contains either a whole input vector or a specific value thereof, according to s. This is easily done with a for loop, or with arrayfun.
  2. Apply one of these answers to generate all combinations.

Code:

%// Inputs
x1 = [1,2];
x2 = [1,2,3];
x3 = [1,2,3];
x4 = [1,2,3];
s = [0 0 2 3];

%// Step 1
x = {x1 x2 x3 x4};
ind = s~=0;
x(ind) = arrayfun(@(y,t) {y{1}(t)}, x(ind), s(ind));

%// Step 2
n = numel(x);
combs = cell(1,n);
[combs{end:-1:1}] = ndgrid(x{end:-1:1});
combs = cat(n+1, combs{:});
combs = reshape(combs,[],n);
Community
  • 1
  • 1
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147