if statement with for loop - matlab

I am writing a function to calculate a value of p.
The formula is p=r*q + pa. The pa value is column vector which i have got from the ode45 function. I have to change the value of q w.r.t time i.e from 0 to 1 sec q=500, from 1 to 2 sec q=0.
I have written this program:
function [p] = fom(t,pa)
r=0.007;
tin=1;
t=0:0.01:2;
if t <=tin
q = 600;
else t <= 2
q = 0;
end
[t,pa]=ode45('FOM1',[t],[0])
for i=[palv]
p=(r*q)+(i);
end
end
The problem is I am getting correct values after 1 sec in my output but before 1 sec where q is 0 values are not changing.
Is this if statement correct?

The problem is the following code snippet:
if t <=tin
q = 600;
else t <= 2
q = 0;
end
With t <= tin, you compare each element of vector t with tin. The result is again a vector, which contains 1 for all elements in t, which are smaller than tin, and 0 for all elements which are larger than tin, i.e.
[ 1 1 ... 1 1 0 0 ... 0 ]
According to the documentation, if evaluates the following:
An expression is true when its result is nonempty and contains only nonzero elements (logical or real numeric). Otherwise, the expression is false.
As the vector contains ones and zeros, i.e. not only nonzero elements, the this always evaluates to false and the else clause will be executed. q will therefore be a scalar, not a vector, which is always 0. To get a vector q, which is 600 for all t <= tin and zero otherwise, you can use
q = 600*(t <= tin);
which creates such a vector as printed above, and multiplies it by 600.
Now, a number of comments on your code:
Regarding the else: in the else, you can't have any other conditions, so t <= 2 will just be executed and printed to the console, but this does nothing, so you can leave that away.
You have t and pa as inputs to the function, but never use them. t is simply overwritten. So either leave t an input and don't overwrite it, or leave it away as input. Further, you can remove pa as input, as you calculate it using ode45.
I assume for i = palv is a typo and should be for i = pa.
In this for loop, by calling p=(r*q)+(i);, p gets overwritten in every iteration, i.e. the resulting p will be r*q plus the last element of pa.
You can create a vector p without a for loop using
p = r*q + pa
Everything together, the function becomes
function p = fom(t)
r=0.007;
tin=1;
q = 600 * (t <= tin);
[t,pa]=ode45('FOM1',[t],[0])
p = r*q + pa
end
and can be called e.g. by
t = 0:0.01:2
p = fom(t);

Related

how to compare all vector indexes with a constant value and switch the value of another variable (0 1) based on that

I have a 1x24 vector (a). I should define a command in Matlab which compare all 24 values of a vector (a) with a certain value (mean (b)) and if the vector (a) item is greater than certain value (mean (b)), ''I'' sets 1 and if the vector item is less than certain value ''I'' sets 0. I wrote the below code:
for i=1:length(a)
if a(i) >= mean(b)
I = 1;
else
I = 0;
end
end
But it implements the comparison only for the last index of vector a and sets I=0. How can I fix the command that do the comparison for all indexes of vector a?
In MATLAB, you can use the following syntax to do so:
I = a >= mean(b);
If you want to use your code for doing so, you'll need to initialize I as a vector, and modify its indices as follows:
I = zeros(length(a),1)
for ii=1:length(a)
if a(ii) >= mean(b)
I(ii) = 1;
else
I(ii) = 0;
end
end
You should read about logical indexing in matlab. You don't need for loops for what you are doing. For example, if you have,
rng(5);
a = rand(1,10);
b = 0.5;
then, I = a > b; will return a logical array with zeros and ones, where one indicates the position in the array where the given condition is satisfied,
I =
0 1 0 1 0 1 1 1 0 0
Using these indices, you can modify your original array. For example, if you wish to change all values of a greater than b to be 10, you would simply do,
a(a > b) = 10;
Specifically, if you need indices where the condition is satisfied, you can use, find(a > b), which in this example will give you,
ans =
2 4 6 7 8

Use recursive MATLAB function or optimization?

I am trying to decide the most efficient, yet most precise approach to calculate a value called R which can only take a value between 0 and 1. Right now I have the below function used in the below script, but I feel like I am doing this in a non-optimal way. Currently I get an answer and have to feed that answer (again) as the initial "guess" in order to get the (next) most optimal answer. Could I build a better recursion for this or perhaps use one of Matlab's solvers? Thanks!
The function:
function f = Rfind(p,u,R)
f = p .* (R.^u);
end
The script:
R = 0.999995753651217; % initial guess
matches = false;
while ~matches && R < 1
R = R + 0.0000000000000000001; % increment R for next guess
Jtotal = sum(Rfind(p,u,R)); % find R
if abs(Jtotal - R)*10000000000 < 5 % check precision of result
matches = true; % if R matches R fed to function, successful
end
end
Jtotal
What I'm trying to identify:
Find a value of R equal to the sum of array p times R to the power of array u. Array p and array u both have the same number of elements, i.e. 12 rows in 1 column each. My function calculates R for each p and u row and then increments its guess to find the next closest match. It stops once the precision limit has been met or the input R and output total are identical.
Example Data:
Array p
0.00000693
0.00000231
0.00001386
0.00000924
0.00041360
0.00461657
0.03085337
0.01595235
0.09614154
0.06832660
0.11103563
0.67262800
Array u
50000
500
50
25
10
7.5
5
3.5
2.5
1.25
1
0
Important: I need the best precision for this but I don't want it taking 10 minutes like it has with extensions of the above.
You can use fminbnd for this:
% first assign p and u
% define the function that you want to minimize:
Rfind = #(R) abs(sum(p.*(R.^u)) - R)
% set the tolerance to maximum:
options = optimset('TolX',eps);
% find the value between 0 to 1 that minimize the function Rfind:
[R, err] = fminbnd(Rfind,0,1,options)
and get (in a fraction of a second):
R =
0.999995761369809
err =
9.196743366857163e-11

Assigning matrix elements to variables in a data set

Hello I'm new to Matlab.
I've written this script :
k2=2*pi();
z1 = 1;
z2 = 2;
z3 = 4;
for l = linspace(0,1,11)
A = [ -1 1 1 0 ; 1 z1/z2 -z1/z2 0 ; 0 exp(-i*k2*l) exp(i*k2*l) -1 ; 0 exp(- i*k2*l) -exp(i*k2*l) -z2/z3];
B = [ 1 ; 1 ; 0 ; 0];
D = inv(A);
C = mtimes(D,B) ;
display(C)
r = C(1,1); % this is supposed to set r = the 1,1 element in the matrix C
t = C(1,4); % see above
end
My idea for taking the values of r and t from C didnt appear to work. How can I do this properly?
Also I want to plot a graph of |r|,|t|, arg(r) and arg(t) for each value of l, my for loop overwrites the values of r and t? how can I either plot one point per loop or make r and t assign the new values so that they become lists of data.
Thanks a lot!
Matlab sets the first dimension of a matrix as row number (i.e. y position).
So you want t=C(4, 1), as you should see that the size of C is 4x1. As a note Matlab is quite good at suppressing singleton dimensions so you could do also do C(1) and C(4).
For your second point you want to set a particular element of r and t in each loop. This is the same as when you access at particular element of C when setting the values. For your case you can use the index l to determine the element. Remembering that in matlab arrays start at element 1 (not 0 as in many other languages). So you want something like r(l+1)=C(1); (or change l to start at 1).
In the more general case if you are not looping over an integer for some reason you may need to create a separate counter variable which you increase in the loop. Also it is good practice to preallocate such arrays when the size is known beforehand, often by r=zeros(11, 1) or similar (note: zeros(11) is an 11x11 matrix). This isn't significant in this case but can drastically increase execution time for large multi-dimensional arrays so is a good practice.

Recursion in Matlab. why is my recursion not working past the first step?

So I am very new to Matlab and I have been tasked with implementing LU factorization. I have to do it recursively because we are not allowed to use for loops in our code, and recursion will give us optimal marks. I have written this code. The code works for the first step, and does what it is supposed to, but for the next two steps, the matrix is not modified at all. I have this code:
function[L, U] = myLU(A,B, pos)
%A = Mtrix that becomes U
%B = Matrix that becomes L
tmp_L = B;
[x,y] = size(A);
if pos > x
L = B;
U = A;
return
else
pos %<-- just to see if it iterates through everything
[tmp_U,tmp_L] = elimMat(A,pos);
myLU(tmp_U,tmp_L, pos+1);
end
L = tmp_L;
U = tmp_U;
end
I where elimMat(A, pos) returns the elimination matrix for column pos. as well as another matrix, which will end up being the matrix of multipliers. What i tried doing is then finding the LU factorization of this matrix A. since elimMat returns L and U(this works, if i do it manually it works), i had to make a function that allows me to do it automatically without using a for loop. I thought i would do it recursively. What i ended up doing is adding another variable B to the function so that i can store intermediate values of my matrix obtained in each step and put it all together later.
So here is my question. Am i implementing the recursion wrong? and if i am how can i fix it? The other thing i wanted to ask is how can i implement this so i do not need variable B as an additional imput, and only use the existing variables, or variables previously defined, to find the solution? I would really like only two inputs in my function: The matrix name and the starting index.
here is elimMat if if helps:
function [M,L] = elimMat(A,k)
%find the size of the matrix
[x,y] = size(A);
tmp_mat = zeros(x,y);
%M = The current matrix we are working on for Elimination -> going to
%become U.
%L = The L part of the matrix we are working on. Contains all the
%multipliers. This is going to be our L matrix.
for i = 1:x
mult = A(i,k)/A(k,k);
if i > k
tmp_mat(i,k) = mult;
P = A(k,:)*mult;
A(i,:) = A(i,:)-P;
elseif i == k
tmp_mat(k,k) = 1;
end
end
M = A;
L = tmp_mat;
end
thanks for any feedback you can provide.
Here is the output: WHAT I GET VS what it should be:
[U = VS [U =
1 2 2 1 2 2
0 -4 -6 0 -4 -6
0 -2 -4] 0 0 2
L = VS [L=
1 0 0 1 0 0
4 0 0 4 1 0
4 0 0] 4 0.5 1
As you can see only the first column is changed
You forgot to catch the output of your recursive call:
[tmp_L, tmp_U] = myLU(tmp_U,tmp_L, pos+1);
Matlab passes variables by value, so a function cannot change its input variable itself (ok, it can, but it's tricky and unsafe).
Your original version didn't return the updated matrices, so the outermost function call encountered the myLU() call, let the recursion unfold and finish, and then went on to use tmp_L and tmp_U as returned from the very first call to elimMAT(A,1).
Note that you might want to standardize your functions such that they return U and L in the same order to avoid confusion.

How does a "for" loop in Matlab change its control variable on each iteration?

>> a = [1 1 2 3 5 8 13 21 13 37];
>> d = [1 2];
>> w = [0 0 0];
for e = d
g = 0;
for f = a
if mod (f, 2) == 0
g = [g f];
end
end
w = [w;g];
end
>> w
The output of W is the matrix
0 0 0
0 2 8
0 2 8
My question is about the for-loops. Do Matlab for-loops take a value, instead of being a logical condition? For example, when looking at 'for f = a' does f take the value of the array A and then the for-loop iterates through F by its columns?
Thanks.
FOR loops have a variable, each pass through the loop the iterator variable takes on the next value in the array. The iterator variable takes on the values of the columns, one at a time. The right hand side of the assignment statement in the foor loop needn't be a numeric array -- it could be a cell array of strings for example, or a structure, etc.
In other words, when you have for
for f=a, ....., end
this is equivalent to writing
for i=1:numel(a)/size(a,1); f=a(:,i); .... ; end
You can easily see this by adding some disp statements into your code:
for e = d
disp(e)
g = 0;
for f = a
disp(f)
if mod (f, 2) == 0
g = [g f];
end
end
w = [w;g];
end
WHILE loops in matlab take a logical condition.
(edit: i forgot that f takes on the value of the columns of a if a is multidimensioned)
Yes, MATLAB loop variables are assigned to "arrays", called vectors in MATLAB parlance. The value of the loop variable automatically iterates over elements of the vector upon each iteration of the loop. A common construct is
for i=1:10 %generates vector of 1,2,...,10
i %will print i=1, i=2, etc.
end
In this case the vector was generated on the fly, and is sequential numbers. But there is no reason you can't pass any arbitrary vector in to iterate over, like "a" in your case. Upon each iteration, "f" takes on the next value in the sequence contained in "a".