MATLAB Answers

0

Combinations of vectors and matrices

Asked by Luca Freilino on 13 Apr 2019
Latest activity Answered by Jan
on 13 Apr 2019
Hi everyone. I have a code (attached at the end) that works. It has as input 6 variables: numbers is a vector, in this case [1 2 2 1], number_surrogates is a vector, value_n and value_a are vectors (of different length), while value_i and value_c are matrices. The problem is that I have to find the final matrix "combinations", which elements are all the possible combinations of the input elements. (eg given comb_n = [1:12], comb_i = [13 14; 13 15; 13 16; ... ; 16 19; 16 20; ....; 28 29], comb_c = [30 31; 30, 32; ...; 35 38; ....; 38 39] and comb_a = [40:47]. the output should be [1 13 14 30 31 40; 1 13 14 30 31 41; ..... ; 3 16 24 36 39 45; ..... ; 12 28 29 38 39 47]. (I wish I had been as much clear as possible). Now, my question is: is there an alternative way to the for cycle? I'm looking for something much faster and computationally better, since loop cycle "kills" the code. Thank you in advance, Luca.
function [comb_n,comb_i,comb_c,comb_a,combinations] = MyFunctionCombinations(numbers,number_surrogates,value_n,value_i,value_c,value_a)
comb_n = nchoosek(value_n,numbers(1));
comb_i = nchoosek(value_i,numbers(2));
comb_c = nchoosek(value_c,numbers(3));
comb_a = nchoosek(value_a,numbers(4));
index = 1;
combinations = zeros((length(comb_n)*length(comb_i)*length(comb_c)*length(comb_a)),number_surrogates,'single');
N = 1:length(comb_n);
I = 1:length(comb_i);
C = 1:length(comb_c);
A = 1:length(comb_a);
for n = N
for i = I
for c = C
for a = A
combinations(index,1:number_surrogates) = [comb_n(n,:), comb_i(i,:), comb_c(c,:), comb_a(a,:)];
index = index+1;
end
end
end
end
end

  4 Comments

Show 1 older comment
Thank you for the suggestions. My input are:
comb_n = [1
2
3
4
5
6
7
8
9
10
11
12]
comb_i = [ 13 14
13 15
13 16
13 17
13 18
13 19
13 20
13 21
13 22
13 23
13 24
13 25
13 26
13 27
13 28
13 29
14 15
14 16
14 17
14 18
14 19
14 20
14 21
14 22
14 23
14 24
14 25
14 26
14 27
14 28
14 29
15 16
15 17
15 18
15 19
15 20
15 21
15 22
15 23
15 24
15 25
15 26
15 27
15 28
15 29
16 17
16 18
16 19
16 20
16 21
16 22
16 23
16 24
16 25
16 26
16 27
16 28
16 29
17 18
17 19
17 20
17 21
17 22
17 23
17 24
17 25
17 26
17 27
17 28
17 29
18 19
18 20
18 21
18 22
18 23
18 24
18 25
18 26
18 27
18 28
18 29
19 20
19 21
19 22
19 23
19 24
19 25
19 26
19 27
19 28
19 29
20 21
20 22
20 23
20 24
20 25
20 26
20 27
20 28
20 29
21 22
21 23
21 24
21 25
21 26
21 27
21 28
21 29
22 23
22 24
22 25
22 26
22 27
22 28
22 29
23 24
23 25
23 26
23 27
23 28
23 29
24 25
24 26
24 27
24 28
24 29
25 26
25 27
25 28
25 29
26 27
26 28
26 29
27 28
27 29
28 29]
comb_c = [ 30 31
30 32
30 33
30 34
30 35
30 36
30 37
30 38
30 39
31 32
31 33
31 34
31 35
31 36
31 37
31 38
31 39
32 33
32 34
32 35
32 36
32 37
32 38
32 39
33 34
33 35
33 36
33 37
33 38
33 39
34 35
34 36
34 37
34 38
34 39
35 36
35 37
35 38
35 39
36 37
36 38
36 39
37 38
37 39
38 39]
and
comb_a = [ 40
41
42
43
44
45
46
47]
Yes, you are right, I didn't write it correctly. All the variables which contain in the name the word "value" are vectors, the ones that starts with "comb" are vectors/matrices
Jan
on 13 Apr 2019
The inputs of your function are:
numbers,number_surrogates,value_n,value_i,value_c,value_a
You provide the first 4 outputs in your comment.
Again: Please provide meaningful input data. If I have to guess them:
fcn([1,2,2,1], 6, 1:12, 13:29, 30:39, 40:47)
% 2nd input is simply sum of first input, I guess
It would be useful to mention the expected maximum size of the inputs also, because combinations tends to explode with growing sizes. It matters if smaller data types as uint16 can be used for indexing.

Sign in to comment.

Products


Release

R2018b

1 Answer

Answer by Jan
on 13 Apr 2019

This is faster:
function [cn, ci, cc, ca, comb] = MyComb4(n, vn, vi, vc, va)
% Get combinations:
cn = nchoosek(single(vn), n(1));
ci = nchoosek(single(vi), n(2));
cc = nchoosek(single(vc), n(3));
ca = nchoosek(single(va), n(4));
% Number of combinations:
scn1 = size(cn, 1);
sci1 = size(ci, 1);
scc1 = size(cc, 1);
sca1 = size(ca, 1);
nCum = cumsum(n);
comb = zeros(nCum(end), scn1 * sci1 * scc1 * sca1, 'single');
index = 0;
v = zeros(nCum(4), 1, 'single');
for in = 1:scn1
v(1:nCum(1)) = cn(in,:);
for ii = 1:sci1
v(nCum(1)+1:nCum(2)) = ci(ii,:);
for ic = 1:scc1
v(nCum(2)+1:nCum(3)) = cc(ic,:);
for ia = 1:sca1
v(nCum(3)+1:nCum(4)) = ca(ia,:);
index = index + 1;
comb(:, index) = v;
end
end
end
end
comb = comb.';
end
The 2nd input is omitted. The output is created column-wise and transposed at the end, which is more efficient.
For the given inouts
[1,2,2,1], 6, 1:12, 13:29, 30:39, 40:47
This takes 0.52 instead of 1.90 sec on my i7, Matlab 2018b.

  0 Comments

Sign in to comment.