Loop doesn't evaluate correctly in MATLAB - matlab

I have a problem with a loop not working correctly for some reason, or maybe it is not the loop itself, but rather something I did not pay attention to. I have been trying to solve the issue for hours now, to no avail.
Here's the code:
syms t;
syms m(t);
Nq=3;
L(1,1)=1;
L(2,1)=2;
L(3,1)=3;
w(1,1)=0.2;
w(2,1)=0.1;
w(3,1)=0.7;
G=1;
for x=1:1:2*Nq
m0val(x)=w(1,1)*L(1,1).^(x-1) + w(2,1)*L(2,1).^(x-1) + w(3,1)*L(3,1 ).^(x-1);
end
ode=diff(m,t)==0;
cond = m(0)==m0val(1);
mf(1)=dsolve(ode,cond);
for x=2:1:2*Nq
ode=diff(m,t)==(x-1)*G*mf(x-1);
cond=m(0)==m0val(x);
mf(x)=dsolve(ode,cond);
end
z=1;
for y=0.2:0.2:1
for x=1:1:2*Nq
mfv(z,x)=subs(mf(x),t,y);
end
for x=1:1:2*Nq+1
P(x,1)=eq(x,1);
end
****for x=1:1:2*Nq+1
if x~=2*Nq+1
P(x,2)=((-1).^(x-1))*mfv(z,x);
else
P(x,2)=0;
end****
end
for y=3:1:2*Nq+1
for x=1:1:2*Nq+2-y
P(x,y)=P(1,y-1)*P(x+1,y-2)-P(1,y-2)*P(x+1,y-1);
end
end
alpha(1)=mfv(z,1);
for x=2:1:2*Nq
alpha(x)=P(1,x+1)/(P(1,x)*P(1,x-1));
end
a(1)=alpha(2);
for x=2:1:Nq
a(x)=alpha(2*x)+alpha(2*x-1);
end
for x=1:1:Nq-1
b(x)=-(alpha(2*x+1)*alpha(2*x)).^0.5;
end
for x=1:1:Nq
Jacobi(x,x)=a(x);
end
for x=1:1:Nq-1
Jacobi (x+1,x)=b(x);
Jacobi(x,x+1)=b(x);
end
[evec,eval]=eig(Jacobi);
for x=1:1:Nq
L(x,z+1)=eval(x,x);
w(x,z+1)=mfv(z,1)*evec(1,x).^2;
end
z=z+1;
end
The bit between * is where it's not working properly, because if I compute let's say P(2,2), it should be equal to (-1)^(1)*mfv(z,2) (where z=1 for the first run). It gives a value of 1 which is the value of P(1,2).

I run your code and I find the issue with P data type. P in your code is logic, therefore, it can not store double or so value.
I declare P before using it in the loop then the code works fine.
z=1;
P = zeros(2,2);% the add line
for y=0.2:0.2:1
for x=1:1:2*Nq
mfv(z,x)=subs(mf(x),t,y);
end
for x=1:1:2*Nq+1
P(x,1)=eq(x,1);
end
for x=1:1:2*Nq+1
if x~=2*Nq+1
P(x,2)=((-1).^(x-1))*mfv(z,x);
else
P(x,2)=0;
end
end

Related

Matlab executes the first statement even if is false

I have the following function in matlab. I am trying to shuffle a matrix. But somehow matlab keeps executing the code from if even if the statement should go to else. And when it comes to else I have to put some aditional code, even if all it does is **i+1. It is normal for matlab or am I missing something?
function magic_matrix = magicsquare1(matrix,n)
magic_matrix=ones(n,n)*(-1);
i=3-1;
j=4+1;
for ki=1:n
for kj=1:n
if(i<1)
i=n;
end
if(j>n)
j=1;
end
if magic_matrix(i,j) == -1
magic_matrix(i,j)=matrix(ki,kj);
%X = sprintf('i=%d j=%d',i,j);
%disp(X)
i=i-1;
j=j+1;
else
i=i+2;
j=j-1;
if(i>n)
i=1;
end
if(j<1)
j=n;
end
magic_matrix(i,j)=matrix(ki,kj);
% X = sprintf('i=%d / j=%d',i,j);
%disp(X)
i=i-1;
j=j+1;
end
end
end

How to create a new variable name in each iteration in a nested matlab for loop?

I would like to run my function and to create 3 different output varables.
for i=1:3
for j=1:3
Rent_nb = landrent(i,j,Dist);
end
end
And I would like "_nb" to be 1, 2, 3... so I get 3 output arrays.
So I looked on the internet and I saw I had to use this :
http://www.mathworks.com/matlabcentral/answers/29712-creating-a-new-variable-in-each-iteration
So that would give me :
for i=1:3
for j=1:3
eval(['rent' num2str(i) '= landrent(i,j,Dist_lowcost)']);
end
end
This seems to work but I don't really understand it...
I would like to get 9 outputs (one for each combination of i and j) instead of 3.
I guess it has something to do with this part: num2str(i)..
But I don't really understand how this works or what it does.
Can someone explain/help?
Thanks
It may help to write out the command separately (to a string) and then evaluate it, and so you will be able to see exactly what statement is being evaluated:
for i=1:3
for j=1:3
cmd = ['rent' num2str(i) '= landrent(i,j,Dist_lowcost);'];
fprintf('command to evaluate is: %s\n',cmd); % or just step through the code
eval(cmd);
end
end
The output from the above for i==1 is
command to evaluate is: rent1= landrent(i,j,Dist_lowcost)
command to evaluate is: rent1= landrent(i,j,Dist_lowcost)
command to evaluate is: rent1= landrent(i,j,Dist_lowcost)
Note that for every j, we reset rent1 to landrent(i,j,Dist_lowcost) and so that is why you are only getting three outputs - each subsequent iteration over j replaces the previous result.
If you are determined to go ahead with the above and create new variables rather than using a matrix, you could do the following instead - create the renti vector at each iteration of i and then use that as you iterate over j:
for i=1:3
cmd = ['rent' num2str(i) '=zeros(1,3);'];
eval(cmd);
for j=1:3
cmd = ['rent' num2str(i) '(j)= landrent(i,j,Dist_lowcost);'];
fprintf('cmd=%s\n',cmd);
eval(cmd);
end
end

Matlab takes only 4 values of a digit for calculation

I wrote a code to combine zeros in a matrix.For example,if there are 3 zeros,then l will be equal to 0.3 and 0.3 will be put into the matrix B.If any other numbers are there, then they are put into matrix B without any change.
k=1;l=0;i=1;
A=J;
xx=size(A,2);
while(i<=xx)
if(A(i)~=0)
if(i==1 || A(i-1)~=0)
B(k)=A(i);
k=k+1;
i=i+1;
else
if(A(i-1)==0)
str=num2str(l);
if(mod(l,10)==0)
str=fliplr(str);
str2=strcat('0.',str);
else
str2=strcat('0.',str);
end;
num=str2num(str2);
B(k)=num;
k=k+1;
B(k)=A(i);
k=k+1;
i=i+1;
l=0;
end;
end;
else
l=l+1;
i=i+1;
end;
end;
if(l~=0)
str=num2str(l);
str2=strcat('0.',str);
num=str2num(str2);
B(k)=num;`
end;
Here,the value of 'l' became equal to 23440 and only the value 2344 was taken.So instead of 0.04432, matlab is storing this as 0.2344.How do I make 'l' take the value 23440?
If the array ends in zeros (or contains only zeros), the statement if(mod(l,10)==0) ... is not executed. Instead the branch under if(l~=0) at the end of the script is executed, and the function fliplr is not used there.
You should probably write a function to take l as an input and return the number that should be appended to B. Then you can call that function in both places where you needed to deal with zeros. (Also I would rename l to something that looks less like 1, but that's not why the script doesn't work.)

While loop inside for loop in Matlab

I am trying to using a while loop inside a for loop in Matlab. The while loop will repeat the same action until it satifies some criteria. The outcome from the while loop is one iteration in the for loop. I am having a problem to get that correctly.
n=100;
for i=1:n
while b<0.5
x(i)=rand;
b=x(i);
end
end
I am not sure what i am doing wrongly.
Thanks
Approach the problem differently. There's no need to try again if rand doesn't give you the value you want. Just scale the result of rand to be in the range you want. This should do it:
x = 0.5 + 0.5*rand(1, 100);
With the example you showed, you have to initialize b or the while-statement cannot be evaluated when it is first called.
Do it inside the for-loop to avoid false positives after the first for-iteration:
n=100;
for ii=1:n
b = 0;
while b<0.5
x(ii)=rand;
b=x(ii);
end
end
Or, without b:
n=100;
x = zeros(1,100);
for ii=1:n
while x(ii)<0.5
x(ii)=rand;
end
end

Using struct arrays in parfor

I am having trouble using struct arrays in Matlab's parfor loop. The following code has 2 problems I do not understand:
s=struct('a',{},'b',{});
if matlabpool('size')==0
matlabpool open local 2
end
for j = 1:2
parfor k=1:4
fprintf('[%d,%d]\n',k,j)
s(j,k).a = k;
s(j,k).b = j;
end
end
matlabpool close
It fails with an error Error using parallel_function (line 589)
Insufficient number of outputs from right hand side of equal sign to satisfy assignment.
On output, variable s is a vector, not an array (as it should be, even if the code breaks before finishing).
EDIT the problem is solved if I initialize the struct arrays to the correct size, by:
s=struct('a',cell(2,4),'b',cell(2,4));
However, I would still be happy to get insights about the problem (e.g is it rally a bug, as suggested by Oleg Komarov)
It was originally working fine for me but then I don't know what happens. In general you need to be careful with parfor loops and there are ample documentation on how to align everything. Two different words of advice.
First and more importantly, the parfor loop is on the outside loop:
function s = foo
s=struct('a',{},'b',{});
parfor j = 1:2
for k=1:4
fprintf('[%d,%d]\n',k,j)
s(j,k).a = k;
s(j,k).b = j;
end
end
Two, Matlab gets very picky about writing the main exit variable (i.e. the variable contained in the parfor loop which is indexed to the loop, in your case, s). You first want to create a dummy variable that holds all the innerloop information, and then writes to it once at the end of the loops. Example:
function s = khal
s=struct('a',{},'b',{});
parfor j = 1:2
dummy=struct('a',{},'b',{});
for k=1:4
fprintf('[%d,%d]\n',k,j)
dummy(k).a = k;
dummy(k).b = j;
end
s(j,:) = dummy;
end
You don't have a problem here, but it can get complicated in other instances