Combinations of vectors and matrices
이전 댓글 표시
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
Loops do not "kill" code. I do not know a definition of "computationally better", but "faster" is clear. Can you provide a set of inputs, which are relevant for your work? If I invent some inputs, they might be not relevant for your needs.
Note that:
N = 1:100
for n = N
...
end
is less efficient than
for n = 1:100
...
end
length(comb_n) is prone to bugs, because it uses the longest dimension. Use size(comb_n, 1) if the 1st dimension is meant.
Do I see correctly, that number_surrogates equals sum(numbers)? And is numbers the length of the first dimension of the last 4 inputs? Then the first 2 inputs are redundant and should be omitted for clarity.
"value_i and value_c are matrices" - then nchoosek(value_i,numbers(2)) will fail, because nchhosek does not accept matrices as first input. This means, that the posted code is not running, the inputs and the outputs are not clearly defined and the purpose of the code is not exactly defined. In consequence it is not clear, what your questions is: instead of an alternative you might be looking for a working method. Please clarify this to allow us to help you.
A cleaned version of your code - just with nicer names for variables, but not working also:
function [cn, ci, cc, ca, comb] = fcn(n, nSurr, vn, vi, vc, va)
cn = nchoosek(single(vn), n(1));
ci = nchoosek(single(vi), n(2)); % Not working for matrices ?!
cc = nchoosek(single(vc), n(3)); % Not working for matrices ?!
ca = nchoosek(single(va), n(4));
[scn1, scn2] = size(cn);
[sci1, sci2] = size(ci);
[scc1, scc2] = size(cc);
[sca1, sca2] = size(ca);
comb = zeros(scn1 * sci1 * scc1 * sca1, nSurr, 'single');
index = 0;
for in = 1:scn1
for ii = 1:sci1
for ic = 1:scc1
for ia = 1:sca1
index = index + 1;
comb(index, :) = [cn(in,:), ci(ii,:), cc(ic,:), ca(ia,:)];
end
end
end
end
end
Luca Freilino
2019년 4월 13일
Luca Freilino
2019년 4월 13일
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.
답변 (1개)
Jan
2019년 4월 13일
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.
카테고리
도움말 센터 및 File Exchange에서 Logical에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!