Creating a Variable Number of Nested 'for' Loops

8 Ansichten (letzte 30 Tage)
Sarangan Senthilgiri
Sarangan Senthilgiri am 8 Feb. 2018
Bearbeitet: Jan am 8 Feb. 2018
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 Kommentare
Jan
Jan am 8 Feb. 2018
Typo: I guess, that you do not have 3 times "for i", but it should be "for i, for j, for k".
Sarangan Senthilgiri
Sarangan Senthilgiri am 8 Feb. 2018
Thank you for the correction.

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Walter Roberson
Walter Roberson am 8 Feb. 2018
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.

Weitere Antworten (1)

Jan
Jan am 8 Feb. 2018
Bearbeitet: Jan am 8 Feb. 2018
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).

Kategorien

Mehr zu Loops and Conditional Statements finden Sie in Help Center und File Exchange

Tags

Produkte

Community Treasure Hunt

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

Start Hunting!

Translated by