How can I access my vectors indices when I am assigning values? - matlab

I am trying to code something in Matlab and it involves a lot of accessing elements in vectors. Below is a snippet of code that I am working on:
x(1)=1;
for i=2:18
x(i)=0;
end
for i=1:18
y(i)=1;
end
for i = 0:262124
x(i+18+1) = x(i+7+1) + mod(x(i+1),2);
y(i+18+1) = y(i+10+1) + y(i+7+1) + y(i+5+1) + mod(y(i+1), 2);
end
% n can be = 0, 1, 2,..., 262142
n = 2;
for i = 0: 262142
z(i+1) = x(mod(i+n+1, 262143)); %error: Subscript indices must either be real positive integers or logicals.
end
In the last "for" loop where I am initialising vector z(), I get an error saying: "Subscript indices must either be real positive integers or logicals." However, when I do not suppres z(i+1) by ommiting the semi colon, the program is able to run, and I can see the values of z in the workspace. Why is this?
The code I am writing in Matlab is based upon the series of instructions shown in the image below. However, I can't seem to track down my error which leads to me not being able to access the elements of x() (without not suppressing the output of z()).
I appreciate any ideas :-) Thank you!

The code breaks at that loop last iteration because , for i=262140 you get
(mod(i+n+1, 262143)) = 0
so you cant access x(0) in matlab. the first elements of any variable is x(1).
In addition, and not related to your question, this code doesn't use the advantages matlab has, instead of
for i=2:18
x(i)=0;
end
you can just write:
x(2:18)=0;
etc

Related

Implementing forward Euler method in matlab

I'm trying to implement the forward Euler method using matlab, but don't understand the error I'm getting. This is what I have written:
function y = ForwardEulerMethod(f,y0,T,N)
h=T/N;
t=zeros(N+1,1);
for i=0:N
t(i)=i.*h; %line 5
end
y=zeros(N+1,1);
y(0)=y0;
for i=1:N
y(i)=y(i-1)+h.*f(t(i-1),y(i-1));
end
end
My error is with line 5 and says, "Subscript indices must either be real positive integers or logicals." I am familiar with this rule, but don't see how I'm breaking it. I'm just trying to replace a zero at each location in t with a numerical value. What am I missing?
Agree with #vijoc above. You are indexing with 0 at multiple places. You could either change how you are indexing the values or get rid of the for loop altogether, like below:
function y = ForwardEulerMethod(f,y0,T,N)
h=T/N;
t=0:N .* h; % this takes the place of the first for-loop
y=zeros(N+1,1);
y(1)=y0;
for i=2:N+1
y(i)=y(i-1)+h.*f(t(i-1),y(i-1));
end
end
You could even replace the second loop if the function f takes vector inputs like so:
y(1) = y0;
y(2:end) = y(1:end-1) + h .* f(t(1:end-1), y(1:end-1));
You're iterating over i = 0:N and using it as t(i)=i.*h, so you're trying to access t(0) during the first iteration. Matlab indexing starts from 1, hence the error.
You also have other lines which will cause the same error, once the execution gets that far.

Matlab Subscript Index Error

First of all the output of 'find_nbrs' is a row vector. I get the following error (Subscript indices must either be real positive integers or logicals.) at line 13 when evaluating the following code:
function [ N ] = componentt( A,m,found_list )
found_list=[m];
for i = find_nbrs(m,A)
found_list(length(found_list)+1)=i;
end
v=[];
for j=found_list
v=[v find_nbrs(j,A)];
end
v=unique(v);
while length(v)~= length(found_list)
found_list = [found_list v(end)];
for k=v
a=find_nbrs(k,A);
while ~ismember(a,found_list)
v(length(v)+1)=a;
end
end
end
N=sort(found_list); %The entries of the output vector are in increasing order.
end
There are two possible reasons for the
Subscript indices must either be real positive integers or logicals.
error being thrown by the line
found_list = [found_list v(end)];
The first is that you somehow created a variable called end. But since you have posted an entire function which should be scoped I don't think that this is the case.
The second is that v is an empty matrix. In this case what is end? It might be 0. It's definitely not a positive integer though. Try this
v = [];
v(end)
and you'll get the error.
So you need to ask yourself if v should ever be empty by the time you hit that line. If it is, then you need to wrap it in an if statement. So something like
if ~isempty(v)
found_list = [found_list v(end)];
end

Issue with output of an indirect equation using Fzero

I am stuck on trying to write the output of a for loop into a vector. The issue is that once it goes through the equation, it stops and spits out this error: "Subscript indices must either be real positive
integers or logicals."
I've looked into what this error is and I've checked my code. There are no negative integers being output, nor any zeros. The for-loop, function and the fzero command are all good, if I comment out MW4p(y4,:) = MW4 I get all of my answers on the command window. I just can't put them into an array.
for y4 = linspace(1.4,1.67,100)
x0 = 12; %Starting Point
fun = #(MW4) (y4.*MW1.*T3)./(y1.*MW4.*T2) - ...
(((1+((y4+1)./(y4-1)).*p5p2).*((2.*y4)./(y4-1))) ./ ((1+...
((y1+1)./(y1-1)).*p5p2).*((2.*y1)./(y1-1)))) .* (((2./(y1-1))...
./ (2./(y4-1))).^2);
MW4 = fzero(fun,x0)
MW4p(y4,:) = MW4
end
where
y1 = 1.67;
MW1 = 39.55;
T3 = 250; %k
T2 = 700; %k
p5p2 = 2.307; %Determined from T5 desired
MW4p = ones(1,100);
In earlier attempts, I've tried MW4p(y4) = MW4 which had this error: "Attempted to access MW4p(1.4); index must be a
positive integer or logical." So I added a colon. Putting this command outside of the for-loop simply had it access the last value of the loop and return the same error.
The error message is telling you exactly what you need to know. y4 is not an integer. When using vectors, matrices, cells, or arrays you can't index with a non-integer number.
vectors, matrices and arrays are discrete structures that can only be indexed with discrete values, though obviously they can be used to store non-discrete values.
Unless I'm missing something, your choices are:
Through whatever data structure: store y4 and its corresponding MW4 value as a tuple; for example, you might have an array of structs or cells where one element is y4 and another element is the array returned from MW4
Use something like this answer, using a hash map. I haven't looked into this closely, but my guess is you can use a float as the key.

Subscript indices must either be real positive integers or logicals error within Matlab decay program

I am having issues with a code of mine dealing with decay. The error "Subscript indices must either be real positive integers or logicals" continues to occur no matter how many times I attempt to fix the line of code: M=M(t)+h.*F
Here is the complete code so that it may be easier to solve the issue:
M=10000;
M=#(t) M*exp(-4.5*t);
F=-4.5*M(t);
h=.1;
t(1)=0;
tmax=20;
n=(tmax-t(1))/h;
i=1;
while h<=.5
while i<=n
t=t+h;
M=M(t)+h.*F;
data_out=[t,M];
dlmwrite('single_decay_euler_h.txt',data_out,'delimiter','\t','-append');
i=i+1;
end
h=h+.1;
end
Thanks for any help.
In the start, you're setting M = 5000;. In the following line, you're creating an anonymous function also called M:
M=#(t) M*exp(-4.5*t);
Now, your initial M = 5000 variable has been overwritten, and is substituted by the function:
M(t) = 5000 * exp(-4.5*t); %// Note that the first M is used to get 5000
Thereafter you do F = -4.5*M(t). I don't know what the value t is here, but you're giving F the value -4.5 * 5000 * exp(-4.5*t), for some value of t. You are not creating a function F.
In the first iteration of the loop, M=M(t)+h.*F; is interpreted as:
M = 5000 * exp(-4.5*0) + 0.1*F %// Where F has some value determined by previous
%// the function above and the previous value of t
%// -4.5*0 is because t = 0
M is now no longer a function, but a single scalar value. The next iteration t = 0.1. When you do: M=M(t)+h.*F; now, it interprets both the first and second M as a variable, not a function. t is therefore used as an index, instead of being an input parameter to the function M (since you have overwritten it).
When you are writing M(t), you are trying to access the 0.1'th element of the 1x1 matrix (scalar) M, which obviously isn't possible.
Additional notes:
The outer while loop has no purpose as it stands now, since i isn't reset after the inner loop. When you're finished with the first iteration of the outer loop, i is already >n, so it will never enter the inner loop again.
You shouldn't mix variable and function names (as you do with M. Use different names, always. Unless you have a very good reason not to.
data_out=[t,M]; is a growing vector inside a loop. This is considered very bad practice, ans is very slow. It's better to pre-allocate memory for the vector, for instance using data_out = zeros(k,1), and insert new values using indexes, data_out(ii) = M.
It's recommended not to use i and j as variable names in MATLAB as these also represent the imaginary unit sqrt(-1). This might cause some strange bugs if you're not paying attention to it.
You can almost certainly do what you're trying to do without loops. However, the function you have written is not functioning, and it's not explained all too well what you're trying to do, so it's hard to give advice as to how you can get what you want (but I'll give it a try). I'm skipping the dlmwrite-part, because I don't really understand what you want to output.
M = 5000;
t0 = 0;
tmax = 20;
h = 0.1; %// I prefer leading zeros in decimal numbers
t = t0: h: tmax;
data_out = M .* exp(-4.5 * t);
The problem is caused by M(t) in your code, because t is not an integer or logical (t=1,1.1,1.2,...)
You need to change your code to pass an integer as a subscript. Either multiply t by 10, or don't use the matrix M if you don't need it.

Error: Matrix dimensions must agree for plot

having a problem with my "new love", matlab: I wrote a function to calculate an integral using the trapz-method: `
function [L]=bogenlaenge_innen(schwingungen)
R = 1500; %Ablegeradius
OA = 1; %Amplitude
S = schwingungen; %Schwingungszahl
B = 3.175; %Tapebreite
phi = 0:2.*pi./10000:2.*pi;
BL = sqrt((R-B).^2+2.*(R-B).*OA.*sin(S.*phi)+OA.^2.*(sin(S.*phi)).^2+OA.^2.*S.^2.*(cos(S.*phi)).^2);
L = trapz(phi,BL)`
this works fine when i start it with one specific number out of the command-window. Now I want to plot the values of "L" for several S.
I did the following in a new *.m-file:
W = (0:1:1500);
T = bogenlaenge_innen(W);
plot(W,T)
And there it is:
Error using .*
Matrix dimensions must agree.
What is wrong? Is it just a dot somewhere? I am using matlab for the second day now, so please be patient.... ;) Thank you so much in advance!
PS: just ignore the german part of the code, it does not really matter :)
In your code, the arrays S and phi in the expression sin(S.*phi) should have same size or one of them should be a constant in order the code works
The error is most likely because you have made it so that the number of elements in schwingungen, i.e. W in your code, must be equal to the number of elements in phi. Since size(W) gives you a different result from size(0:2.*pi./10000:2.*pi), you get the error.
The way .* works is that is multiplies each corresponding elements of two matrices provided that they either have the same dimensions or that one of them is a scalar. So your code will work when schwingungen is a scalar, but not when it's a vector as chances are it has a different number of elements from the way you hard coded phi.
The simplest course of action (not necessarily the most Matlabesque though) for you is to loop through the different values of S:
W = (0:1:1500);
T = zeros(size(W); %Preallocate for speed)
for ii = 1:length(W)
T(ii) = bogenlaenge_innen(W(ii));
end
plot(W,T)
In your function you define phi as a vector of 10001 elements.
In this same function you do S.*phi, so if S is not the same length as phi, you will get the "dimensions must agree" error.
In your call to the function you are doing it with a vector of length 1501, so there is your error.
Regards