Form a matrix of combinations with vector sets / pairs
I wanted to find all combinations of elements from a set of vectors. I found the following answer which works great. However, some of my vectors are chained together. For example, if I have a vector [15, 20]
and [60, 70]
, I would only like to get a combination of [15, 60]
and [20, 70]
(because you 15
cannot combine with 70
).
Therefore, for the following vectors:
vectors = {[1 2], [3 6 9], [10 20 30]} % [3 6 9] and [10 20 30] are paired
must give
combs = [ 1 3 10
1 6 20
1 9 30
2 3 10
2 6 20
2 9 30 ]
For this simple example, I can use the combination code from the link with vectors = {[1 2], [3 6 9]}
and doing the concatenation to generate the third column:
combs = [combs, repmat([10 20 30], 1, size(combs, 1)/size([10 20 30], 2))'];
However, my business is not so simple. For example, I would like to have some code that works for vectors:
vectors = {[1 2], [3 6 9], [10 20 30], [3 4 5], [55 66 77], [555 666 777], [101 201]}
% [3 6 9] and [10 20 30] are a pair.
% [55 66 77] and [555 666 777] are a pair.
source to share
First, you need to determine which vectors are "related". Using your example,
vectors = {[1 2] [3 6 9] [10 20 30] [3 4 5] [55 66 77] [555 666 777] [101 201]};
linked = [1 2 2 3 4 4 5]; %// equal numbers mean those vectors are linked
Then you can use a slight modification of the mentioned answer:

Reduce each vector to the equivalent vector of values ββ1,2,3, ... Let's call this "intvector".

Create combinations based on only one "representative" intvector from each related set of vectors.

Fill in the copied values ββ(columns) for the rest of the int vectors (associated with their representatives). This is why we use int vectors instead of vectors: each unrepresentative is just a copy of its representative.

Use indexing to translate from int vectors to actual vectors.
code:
intVectors = cellfun(@(x) 1:numel(x), vectors, 'uniformoutput', 0); %// transform
%// each vector into integers 1, 2, 3,...
[~, u, v] = unique(linked);
uIntVectors = intVectors(u); %// choose one intvector as representative of each
%// linked set
m = numel(vectors); %// number of vectors
n = numel(uIntVectors); %// number of representatives (intvectors)
combs = cell(1,n);
[combs{end:1:1}] = ndgrid(uIntVectors{end:1:1});
combs = combs(:,v); %// include nonrepresentatives (linked intvectors)
combs = cat(m+1, combs{:});
combs = reshape(combs,[],m); %// combinations of representatives (intvectors)
num = max(combs, [], 1); %// number of elements of each vector
vectorsCat = [vectors{:}]; %// concatenate all vectors
cnum = cumsum(num(1:end1));
combs(:,2:end) = bsxfun(@plus, combs(:,2:end), cnum); %// transform integers
%// so that they can index vectorsCat
combs = vectorsCat(combs); %// do the indexing to get final result
Let's simplify your litle example for brevity:
vectors = {[1 2], [3 6 9], [10 20 30], [3 4 5]};
linked = [1 2 2 3];
produces
1 3 10 3
1 3 10 4
1 3 10 5
1 6 20 3
1 6 20 4
1 6 20 5
1 9 30 3
1 9 30 4
1 9 30 5
2 3 10 3
2 3 10 4
2 3 10 5
2 6 20 3
2 6 20 4
2 6 20 5
2 9 30 3
2 9 30 4
2 9 30 5
source to share