Hi all,
I am trying to iterate down every column of array x, and extract all combinations when the sum of these elements is equal to one.
At the moment this is being made possible by having a for loop iterate down each individual column, and then using an if statement to pause the loop and store these combinations in the array 'Combinations'.
N = 3;
x = zeros(6, N);
x(1, :) = 0;
x(2, :) = 0.2;
x(3, :) = 0.4;
x(4, :) = 0.6;
x(5, :) = 0.8;
x(6, :) = 1;
a = 0;
A = 1;
for i = 1:size(x, 1)
for j = 1:size(x, 1)
for k = 1:size(x, 1)
X = x(i, 1) + x(j, 1) + x(k, 1);
if X == 1
Combinations(A, 1) = x(i, 1);
Combinations(A, 2) = x(j, 2);
Combinations(A, 3) = x(k, 3);
a = a + 1;
A = A + 1;
continue
end
end
end
end
However, if the number of columns in x were to change, I would need to be able to vary the number of for loops depending on the value of N. Is this possible/is there an alternative method of achieving a similar result?
Any help would be appreciated. Thanks!

댓글 수: 3

KSSV
KSSV 2018년 2월 8일
What exactly are you trying?
Jan
Jan 2018년 2월 8일
Typo: I guess, that you do not have 3 times "for i", but it should be "for i, for j, for k".
Thank you for the correction.

댓글을 달려면 로그인하십시오.

 채택된 답변

Walter Roberson
Walter Roberson 2018년 2월 8일

0 개 추천

Use https://www.mathworks.com/matlabcentral/fileexchange/10064-allcomb-varargin- allcomb() from the File Exchange, and then throw away the entries that do not match your constraint.

추가 답변 (1개)

Jan
Jan 2018년 2월 8일
편집: Jan 2018년 2월 8일

0 개 추천

Attention: Consider rounding effects:
0.1 + 0.1 + 0.1 == 0.3 % FALSE!!!
So do not check if the sum equals 1.0 exactly, but if the distance is smaller than a specific limit, e.g. 3*eps.
You can use an index vector of variable size instead of a set of loops. See e.g. https://www.mathworks.com/matlabcentral/answers/333926-recursive-function-for-replacing-multiple-for-loops#answer_262156 .
N = 3;
% x = zeros(6, 1); % Not [6, N] Or easier:
x = [0, 0.2, 0.4, 0.6, 0.8, 1.0];
nx = numel(x);
Lim = 30 * eps; % Consider rounding errors!!!
v = [1, 1, 1]; % ONE index vector
ready = false;
Combinations = zeros(1e6, N); % Bold pre-allocation
iC = 1;
while ~ready
% Test value and store result:
if abs(sum(x(v)) - 1.0) < Lim % Not: sum(x(v)) == 1.0 !!!
Combinations(iC, :) = v;
iC = iC + 1;
end
% Shift the index vector:
ready = true; % Claim temporarily that the WHILE loop is ready
for k = 1:N
v(k) = v(k) + 1;
if v(k) <= nx
ready = false;
break; % v(k) increased successfully, leave "for k" loop
end
v(k) = 1; % v(k) reached nx: reset it, proceed with next v
end
end
Combinations = Combinations(1:iC); % Crop the pre-allocated array
This is equivalent to N for loops running from 1 to nx. It is easy to adjust it to specific limits for each loop.
It is much cheaper to pre-allocate a too large array, than letting an array grow iteratively.
For the efficient creation of permutations with repetitions and order see the fast C-Mex function FEX: VChooseKRO (must be compiled before using).

카테고리

도움말 센터File Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기

제품

태그

질문:

2018년 2월 8일

편집:

Jan
2018년 2월 8일

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by