How to put the second "for" loop inside the first one?

Hi,
I need to combine two "for" loops.
I actually need the second loop (c and t arrays) to pass through all the results from the first one (a and b). This means a total of 4 results, because the permutations of a and b would be 4.
I have combined them, but it does not work. The output is only 2 results, while they should be 4.
First loop:
close all; clc; clear all;
a = [1 2 3 4 5];
b = [1 2 3 3 5];
for i=1:5;
for j=1:5;
for k = ((i-1)*5)+ j;
line1 = ['set m1 ' num2str(c(i)) ';'];
line2 = ['set m2 ' num2str(s(j)) ';'];
line3 = ['set case ' num2str(t(k)) ';'];
fid=fopen('MatParam8.0.tcl','w');
fprintf(fid,'%s\n',line1);
fprintf(fid,'%s\n',line2);
fprintf(fid,'%s\n',line3);
fid=fclose('all');
!OpenSees Model.tcl
end
end
end
Second loop:
fin = 'result_all.txt';
s = dlmread(fin,'');
c=[1 2 3 4 5];
t=[1 2 3 4 5];
for j = 1:400;
fidP = fopen('Pulse.acc','w+');
fidC= fopen('Case.tcl','w+');
fprintf(fidP, '%d\n%d\n%d',c(j), s(j), t(j));
fprintf(fidC, 'set case %d',j);
fclose(fidP);
fclose(fidC);
!OpenSees Model.tcl
end
The combination:
close all; clc; clear all;
a = [1 2];
b = [1 2];
for i=1:2;
for j=1:2;
for k = ((i-1)*2)+ j;
line1 = ['set m1 ' num2str(a(i)) ';'];
line2 = ['set m2 ' num2str(b(j)) ';'];
line3 = ['set case ' num2str((k)) ';'];
fid=fopen('MatParam8.0.tcl','w');
fprintf(fid,'%s\n',line1);
fprintf(fid,'%s\n',line2);
fprintf(fid,'%s\n',line3);
fid=fclose('all');
fin = 'result_all.txt';
s = dlmread(fin,'');
c=[1 2];
t=[1 2];
for m = 1:4;
fidP = fopen('Pulse.acc','w+');
fidC= fopen('Case.tcl','w+');
fprintf(fidP, '%d\n%d\n%d',c(m), s(m), t(m));
fprintf(fidC, 'set case %d',j);
fclose(fidP);
fclose(fidC);
!OpenSees Model.tcl
end
end
end
end

16 commentaires

I don't mean this to be offensive in any way, but do you understand how indexing within a for loop works? I have seen a number of your questions come up lately, and while we as a community are happy to help, it seems the bigger issue is teaching you how to index a loop, rather than how to specifically solve this problem. Does that make sense?
Ismail Qeshta
Ismail Qeshta le 25 Fév 2019
Modifié(e) : Ismail Qeshta le 25 Fév 2019
Hi Bob,
Many thanks for your comment.
No problem. Not really actually. I am not sure how to do the indexing. I always get confused when it comes to complex "for" loops. I do apologize if my questions were a little unsophisticated.
Maybe, the best can be to provide me any link, from which I can learn the indexing and resolve this issue in my code.
Not a problem, we all had to learn at some point. I just think helping you learn how to index will help you learn to solve some of these questions on your own, so you don't have to keep waiting on us to respond.
Take a look at this tutorial, and let me know if you have questions. Then we can at least establish a baseline of what you do, or do not know.
Ismail Qeshta
Ismail Qeshta le 25 Fév 2019
Modifié(e) : Ismail Qeshta le 26 Fév 2019
Thank you Bob for the link. I have gone through it.
So, in the case when we have data in a raw (Example 3 in the link), "for" loop reads every single value. That is the simplest example I think. It is very clear up to here.
Can we relate that to my code?
So, it is generally possible to do what you're asking, as Ex. 3 shows, but a more common method is to create the loop with an index of integers, and then index an array which contains the specific values. This can be useful whenever you are calling multiple arrays, or when you want to know how many times your loop has completed, or other counting functions.
A = [24,18,17,23,28];
for a = 1:length(A); % Integer indexes from 1 to the number of elements in A
disp(A(a))
end
Ismail Qeshta
Ismail Qeshta le 26 Fév 2019
Modifié(e) : Ismail Qeshta le 26 Fév 2019
Hi Bob,
Many thanks for your explanation. Alright. Now that this is clear for me, as how the loop bascially works.
Does it mean that I shuould put 1:length(a) and 1:length(b) for i and j in the first loop in my code? Wouldn't that be the same as putting numbers?
You can definitely use the numbers rather than length(), but if you ever change the size of a or b, then you have to manually change the index range of your loops. I personally got tired of doing that and have made a habit of making loop sizes reactive.
Thank you Bob for your reply. Alright then.
Actually, that still has not resolved my confusion with respect to the outcome of the "for" loop.
The "for" still gives me the same error, even though I changed in the length as per the above discussion.
I'm going to focus on this loop:
c=[1 2];
t=[1 2];
for m = 1:4;
fidP = fopen('Pulse.acc','w+');
fidC= fopen('Case.tcl','w+');
fprintf(fidP, '%d\n%d\n%d',c(m), s(m), t(m));
fprintf(fidC, 'set case %d',j);
fclose(fidP);
fclose(fidC);
!OpenSees Model.tcl
end
You are definitely going to receive an error when executing the last two loops (m = 3 and m = 4) because you are calling c(m), which means you are looking at elements 3 and 4 of the c array. Because they don't exist, you get an error 'Index exceeds matrix dimentions.' I don't know if that's the specific error message you're getting, as you haven't posted a specific error message on this thread.
That aside, because you are looking to loop through two separate arrays, you really need two separate loops. If you look at the first set of loops you have you will notice there is one for a, and one for b. This is the 'safest' and simplest way of looping through two separate loops, and is generally your solution here.
Ismail Qeshta
Ismail Qeshta le 26 Fév 2019
Modifié(e) : Ismail Qeshta le 26 Fév 2019
Hi Bob,
Many thanks for your reply. Sorry, that was a mistake. I actually meant m=2. Now the error of 'Index exceeds matrix dimensions' is over.
What I am facing mainly now is acutally that the OpenSees file needs to run through both loops. The second loop needs to go through each output from the first loop.
Would it be possible to explain more what you mean by two separate loops? are they supposed to be in separate Matlab files? or two loops within the same file, but the first need to end; then the second one should start as shown below?
I really hope if they are both in the same file, just to save time and effort.
The updated code:
close all; clc; clear all;
a = [1 2];
b = [1 2];
for i=1:2;
for j=1:2;
for k = ((i-1)*2)+ j;
line1 = ['set fc ' num2str(a(i)) ';'];
line2 = ['set fy ' num2str(b(j)) ';'];
line3 = ['set case ' num2str((k)) ';'];
fid=fopen('MatParam8.0.tcl','w');
fprintf(fid,'%s\n',line1);
fprintf(fid,'%s\n',line2);
fprintf(fid,'%s\n',line3);
fid=fclose('all');
!OpenSees Model.tcl
end
end
end
fin = 'result_all.txt';
s = dlmread(fin,'');
c=[0 0];
t=[0 0];
for m = 1:2;
fidP = fopen('Pulse.acc','w+');
fidC= fopen('Case.tcl','w+');
fprintf(fidP, '%d\n%d\n%d',c(m), s(m), t(m));
fprintf(fidC, 'set case %d',j);
fclose(fidP);
fclose(fidC);
!OpenSees Model.tcl
end
for i=1:2;
for j=1:2;
for k = ((i-1)*2)+ j;
line1 = ['set fc ' num2str(a(i)) ';'];
line2 = ['set fy ' num2str(b(j)) ';'];
line3 = ['set case ' num2str((k)) ';'];
fid=fopen('MatParam8.0.tcl','w');
fprintf(fid,'%s\n',line1);
fprintf(fid,'%s\n',line2);
fprintf(fid,'%s\n',line3);
fid=fclose('all');
!OpenSees Model.tcl
end
end
end
If you look at this portion of code you will notice that there are three separate callings of the 'for' loop command. One is indexed with i, one with j, and the last with k. This is what I mean by separate loops. Instead of having you internal loop, indexed with m, run from m = 1:4, break the loop apart into two separate loops to account for the different arrays c and t.
for m = 1:length(c)
for n = 1:length(t)
fidP = fopen('Pulse.acc','w+');
fidC= fopen('Case.tcl','w+');
fprintf(fidP, '%d\n%d\n%d',c(m), s(m*n), t(n));
fprintf(fidC, 'set case %d',j);
fclose(fidP);
fclose(fidC);
!OpenSees Model.tcl
end
end
Hi Bob,
Many thanks for your reply and corrections.
I actually have the following two comments:
1) Why did we have to do the multiplication (m*n) for s?
2) Regarding the case in both loops. I just thought of re-eplaining what I exactly mean by case in my code, so you can help me in following up the source of error.
For each case in the first loop, there should be two cases. Hence,
First loop | Second loop
Case: 1 | 1, 2
2 | 3, 4
3 | 5, 6
4 | 7, 8
In other words, the second loop should read each case from the first loop "twice".
I hope it is clear now.
To achieve this, I thought of removing the case in the first loop, so only the second loop can count the cases for my model, but it does not seem to work. Also, I just noticed that we use
fprintf(fidC, 'set case %d',j);
I replaced j with m, but in this case, the cases keep over-writing each other in the output files, although the code runs 8 times, which is eactly what I want. By further checking, yes the last output is basically two files for case 7 and 8.
The updated code is as follows:
close all; clc; clear all;
a = [100 200];
b = [100 200];
for i=1:2;
for j=1:2;
% for k = ((i-1)*2)+ j;
line1 = ['set fc ' num2str(a(i)) ';'];
line2 = ['set fy ' num2str(b(j)) ';'];
% line3 = ['set case ' num2str((k)) ';'];
fid=fopen('MatParam8.0.tcl','w');
fprintf(fid,'%s\n',line1);
fprintf(fid,'%s\n',line2);
% fprintf(fid,'%s\n',line3);
fid=fclose('all');
!OpenSees Model.tcl
end
end
% end
fin = 'result_all.txt';
s = dlmread(fin,'');
c=[0 0];
t=[0 0];
for m = 1:length(c)
for n = 1:length(t)
fidP = fopen('Pulse.acc','w+');
fidC= fopen('Case.tcl','w+');
fprintf(fidP, '%d\n%d\n%d',c(m), s(m*n), t(n));
fprintf(fidC, 'set case %d',m);
fclose(fidP);
fclose(fidC);
!OpenSees Model.tcl
end
end
I used s(m*n) with the intention of moving through all four elements of s. Ultimately, this was erroneous because it will produce [1 2 2 4] as its indexes instead of the desired [1 2 3 4]. Feel free to correct it as needed, as I haven't looked over the structure of s in detail.
Yes, replacing j with m will only produce the last two files, because m can only ever be [1 2]. I would suggest introducing a new counter within your code to produce individual outputs for each result calculated. This will also solve the indexing of s (if you want a different value for each loop).
count = 0; % Initialize
for m ...
for n ...
count = count + 1;
...
fprintf(fidP, '%d\n%d\n%d',c(m), s(count), t(n));
fprintf(fidC, 'set case %d',count);
...
end
end
Ismail Qeshta
Ismail Qeshta le 26 Fév 2019
Modifié(e) : Ismail Qeshta le 26 Fév 2019
Hi Bob,
Many thanks for your comment.
I actually did try it, I keep getting only 4 results. Also, I am not sure why it starts with case 4, then 1, 2, 3.
I am also not sure how the two loops actually work.
I mean, my aim is actually that the first loop performs for the first case (or permutation), then the second loop starts, then the first loop again performs for the second case (or perutation), then the second loop starts, and so on.
I have corrected the values of m and n.
The updated code:
close all; clc; clear all;
a = [100 200];
b = [100 200];
for i=1:2;
for j=1:2;
% for k = ((i-1)*2)+ j;
line1 = ['set fc ' num2str(a(i)) ';'];
line2 = ['set fy ' num2str(b(j)) ';'];
% line3 = ['set case ' num2str((k)) ';'];
fid=fopen('MatParam8.0.tcl','w');
fprintf(fid,'%s\n',line1);
fprintf(fid,'%s\n',line2);
% fprintf(fid,'%s\n',line3);
fid=fclose('all');
!OpenSees Model.tcl
end
end
% end
fin = 'result_all.txt';
s = dlmread(fin,'');
c=[0 0];
t=[0 0];
count = 0; % Initialize
for m = 1:length(c)
for n = 1:length(t)
count = count + 1;
fidP = fopen('Pulse.acc','w+');
fidC= fopen('Case.tcl','w+');
fprintf(fidP, '%d\n%d\n%d',c(m), s(m), t(m));
fprintf(fidC, 'set case %d',count);
fclose(fidP);
fclose(fidC);
!OpenSees Model.tcl
end
end
Nested loops work in such a way that for each of the outer loop runs, the entirety of the inner loop is performed. Suppose we have two loops, with indices x and y.
for x = 1:4;
for y = 1:2;
disp([x,y])
end
end
If you run that code you will notice the output begins with both x and y as 1, but on the next output of the disp x remains as 1 while y becomes 2. The inner loop is now complete, and the exterior loop can now proceed. So x becomes 2, and y resets to 1. The fourth row shows that both x and y are two. This continues until all iterations of the outer loop have been completed.
Alternatively, if you have for loops in a series, the first loop runs fully to completion, and then the second runs fully to completion.
x = 1; y = 1;
for x = 1:4;
disp([x,y])
end
for y = 1:2;
disp([x,y])
end
This produces a series of display outputs where x and y both start at 1 again, but on the second disp x will be 2, and y still 1. On the third x becomes 3, with y unchanged, and so on until the end of the first loop. The second loop then executes, and the first pass displays x as 4 and y as 1 a second time, before the final pass of the loop displays x as 4 and y as 2.
Does that help you understand better the difference between series and nested loops?
I would suggest that you need to use nested loops because you want to run your second loop each time you run your first loop.
Also, I would suggest moving count to before the beginning of the first loop (before for i = ...).
Ismail Qeshta
Ismail Qeshta le 27 Fév 2019
Modifié(e) : Ismail Qeshta le 27 Fév 2019
Hi Bob,
Many thanks for your explanation.
I have thought of the code and modified it. It finally works.
Yes, you are right. I need nested "for" loop.
I have also shifted the counter above the first loop, but counted only after the second loop.
The code is shown below for your kind reference.
Thank you very much for all your time and effort. That was a great learning exercise.
close all; clc; clear all;
a = [100];
b = [100];
count = 0; % Initialize
for i=1:1;
for j=1:1;
line1 = ['set m1 ' num2str(a(i)) ';'];
line2 = ['set m1 ' num2str(b(j)) ';'];
fid=fopen('MatParam8.0.tcl','w');
fprintf(fid,'%s\n',line1);
fprintf(fid,'%s\n',line2);
fid=fclose('all');
fin = 'result_all.txt';
s = dlmread(fin,'');
c=[0 0];
t=[0 0];
for m = 1:2;
count = count + 1;
fidP = fopen('Pulse.acc','w+');
fidC= fopen('Case.tcl','w+');
fprintf(fidP, '%d\n%d\n%d',c(m), s(m), t(m));
fprintf(fidC, 'set case %d',count);
fclose(fidP);
fclose(fidC);
!OpenSees Model.tcl
end
end
end

Connectez-vous pour commenter.

Réponses (0)

Catégories

En savoir plus sur Loops and Conditional Statements dans Centre d'aide et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by