I am given a function, f(x)= 5*sin(x)*exp(-x-0.2)-1, and I want to find a root using fixed point iteration. The instruction told me to re-arrange the equation to get x=g(x).
So I converted it to x=-ln[1/(5sin(x)]-0.2
I want to make a while loop that satisfies x(1+i)=g(i) relationship as I update x, until x converges. I am guessing that the 'converging' here means that abs(x(i)-x(i+1)) is very small, but not so sure.
x(1)=1;
while abs(x(i+1)-x(i)>0.0001 && i<50
g(i)=-log(1/(5*sin(x(i))))-0.2;
x(i+1)=g(i);
end
My code is obviously wrong. I know I have to update i like, i=i+1; somewhere, but I don't know how I should apply it. also, I see that I haven't declared x(1+1) in the beginning, and that's where I am getting an error from, but... no clue how to fix it.
please help.
If you want to do it in a while loop, then you need to do the first iteration outside the while loop:
x(1) = 1;
x(2) = -log(1/(5*sin(x(1)))) - 0.2;
i = 2;
max_iter = 50;
while (abs(x(i) - x(i-1)) > 0.0001) && (i < max_iter)
x(i+1) = -log(1/(5*sin(x(i)))) - 0.2;
i = i + 1;
end
Alternatively you could test for the number of elements of x in the while condition but that less elegant.
Put the test for convergence inside the loop since you have only one value of x to start with:
x(1) = 1;
max_iter = 50;
for i = 1 : max_iter
x(i+1) = -log(1/(5*sin(x(i)))) - 0.2;
if abs(x(i+1) - x(i)) < 0.0001
break; end
end
Related
I defined two same size vectors t and coverage in Matlab, and I need to define a third vector n_steps.
In particular I need to speed up the following loop:
t = 1:100000;
coverage = double(rand(size(t)) > 0.9);
for j=1:(length(t)-1)
n_steps(j)=0;
while coverage(j+n_steps(j)+1)==0 && j+n_steps(j)+1<length(t)
n_steps(j)=n_steps(j)+1;
end
end
t is a time vector, and coverage at each time step can be 1 or 0.
For each instant t(j) I must find the number of time steps n_steps(j) to wait before the first 1 appears in the vector coverage(j+1:length(coverage)),
Your code (with the example data I added to it) runs in 0.0163 s on MATLAB Online. Just adding
n_steps = zeros(1,length(t)-1);
before the loop reduces the execution time to 0.0057 seconds. Preallocation is very important!
Next, I was able to change your code a bit, such that you don't need to search through the same array over and over again:
n_steps = zeros(1,length(t)-1);
cov = [find(coverage), length(t)];
k = 1;
for j=1:(length(t)-1)
if cov(k) <= j
k = k+1;
end
n_steps(j) = cov(k) - j - 1;
end
This code runs in 0.0015 seconds. It relies on creating a smaller array, cov, that contains the indices to non-zero elements in coverage. cov(k) is the index into coverage for a non-zero element. As we move j forward, sometimes we need to move the index k forward too, such that cov(k) comes after j.
It might be possible to further vectorize the outer loop, but I doubt it will make the code much faster.
This is the script I wrote for timing and testing correctness:
t = 1:100000;
coverage = double(rand(size(t)) > 0.9);
timeit(#() method1(t, coverage))
timeit(#() method2(t, coverage))
timeit(#() method3(t, coverage))
a = method1(t, coverage);
b = method3(t, coverage);
assert(isequal(a,b))
function n_steps = method1(t, coverage)
for j=1:(length(t)-1)
n_steps(j)=0;
while coverage(j+n_steps(j)+1)==0 && j+n_steps(j)+1<length(t)
n_steps(j)=n_steps(j)+1;
end
end
end
function n_steps = method2(t, coverage)
n_steps = zeros(1,length(t)-1);
for j=1:(length(t)-1)
while coverage(j+n_steps(j)+1)==0 && j+n_steps(j)+1<length(t)
n_steps(j) = n_steps(j)+1;
end
end
end
function n_steps = method3(t, coverage)
n_steps = zeros(1,length(t)-1);
cov = [find(coverage), length(t)];
k = 1;
for j=1:(length(t)-1)
if cov(k) <= j
k = k+1;
end
n_steps(j) = cov(k) - j - 1;
end
end
I don't know where to go with this. I think I have the right stuff down but I don't understand.
https://imgur.com/a/V6gdDdr
It keeps running the loop forever and I don't know why.
n=9;
r =0;
p = 0;
syms x
v=1.7;
while abs(v-r) > 10^(-5)
n=n+1;
r = 0;
a = 0;
b= 1/n;
for i = 1:n
r = r + exp(((i+1)+exp(i))/2)*(b-a)
end
['done']
end
The output should be 85. But I'm getting like a couple thousand. I have tried changing the equation in the for loop but I do not know why it is giving me symbolic errors.
Several problems with the posted code:
The parentheses are misaligned in the r=r + ... statement
Instead of exp(i) and exp(i+1), you should use exp(bi) and exp(b(i+1)) in order to account for the given spacing.
Your value of "v" which is supposed be the exact answer should equal e-1, which is 1.71828. Using the approximate 1.7 is going to be very problematic when you are trying to converge to the exact solution within 5 decimal places.
Your for loop should go from 0 to n-1, this way you don't add up any values past your integral range.
n=9;
r =0;
p = 0;
v=e-1;
while abs(v-r) > 10^(-5)
n=n+1;
r = 0;
a = 0;
b= 1/n;
for i = 0:n-1
r = r + ((exp(b*(i+1))+exp(b*i))/2)*(b-a);
end
end
I am trying to implement the Gauss-Seidel method in MATLAB. But there are two major mistakes in my code, and I could not fix them:
My code converges very well on small matrices, but it never converges on large matrices.
The code makes redundant iterations. How can I prevent from redundant iterations?
Gauss-Seidel Method on wikipedia.
N=5;
A=rand(N,N);
b=rand(N,1);
x = zeros(N,1);
sum = 0;
xold = x;
tic
for n_iter=1:1000
for i = 1:N
for j = 1:N
if (j ~= i)
sum = sum + (A(i,j)/A(i,i)) * xold(j);
else
continue;
end
end
x(i) = -sum + b(i)/A(i,i);
sum = 0;
end
if(abs(x(i)-xold(j))<0.001)
break;
end
xold = x;
end
gs_time=toc;
prompt1='Gauss-Seidel Method Time';
prompt2='x Matrix';
disp(prompt2);
disp(x);
disp(prompt1);
disp(gs_time);
First off, a generality. The Gauß-Seidel and Jacobi methods only apply to diagonally dominant matrices, not generic random ones. So to get correct test examples, you need to actually constructively ensure that condition, for instance via
A = rand(N,N)+N*eye(N)
or similar.
Else the method will diverge towards infinity in some or all components.
Now to some other strangeness in your implementation. What does
if(abs(x(i)-xold(j))<0.001)
mean? Note that this instruction is outside the loops where i and j are the iteration variables, so potentially, the index values are undefined. By inertia they will accidentally both have the value N, so this criterion makes at least a little sense.
What you want to test is some norm of the difference of the vectors as a whole, thus using sum(abs(x-xold))/N or max(abs(x-xold)). On the right side you might want to multiply with the same norm construction applied to x so that the test is for the relative error, taking the scale of the problem into account.
By the instructions in the given code, you are implementing the Jacobi iteration, computing all the updates first and then advancing the iteration vector. For the Gauß-Seidel variant you would need to replace the single components in-place, so that newly computed values are immediately used.
Also, you could shorten/simplify the inner loop
xold = x;
for i = 1:N
sum = b(i);
for j = 1:N
if (j ~= i)
sum = sum - A(i,j) * x(j);
end
end
x(i) = sum/A(i,i);
end
err = norm(x-xold)
or even shorter using the language features of matlab
xold = x
for i = 1:N
J = [1:(i-1) (i+1):N];
x(i) = ( b(i) - A(i,J)*x(J) )/A(i,i);
end
err = norm(x-xold)
%Gauss-seidal method for three equations
clc;
x1=0;
x2=0;
x3=0;
m=input('Enter number of iteration');
for i=1:1:m
x1(i+1)=(-0.01-0.52*x2(i)-x3(i))/0.3
x2(i+1)=0.67-1.9*x3(i)-0.5*x1(i+1)
x3(i+1)=(0.44-0.1*x1(i+1)-0.3*x2(i+1))/0.5
er1=abs((x1(i+1)-x1(i))/x1(i+1))*100
er2=abs((x2(i+1)-x2(i))/x2(i+1))*100
er3=abs((x3(i+1)-x3(i))/x3(i+1))*100
if er1<=0.01
er2<=0.01
er3<=0.01
break;
end
end
I have written a function that estimates the inverse of e and loops through values of n until the approximated value is within a given tolerance of the actual value.
Currently I use this code:
function [approx, n] = calc_e(tolerance)
for n = 1:inf
approx = ((1-1/n)^n);
diff = (1/exp(1)) - approx;
if diff < tolerance, break; end
end
end
This works fine however I have been told that it could be more efficient by using a while loop but I can't work out how to do it in that way.
Can anybody shed some light on this?
Simply do:
function [approx, n] = calc_e(tolerance)
n = 1;
while (1/exp(1)) - ((1-1/n)^n) >= tolerance
n = n + 1;
end
end
I tried to write the 'dumb' version of Euler's method using Matlab but I always came up with nothing. My code was trash :-(
See this pseudocode for this method :
‘set integration range
xi = 0
xf = 0
‘initialize variables
x = xi
y = 1
‘set step size and determine
‘number of calculation steps
dx = 0.5
nc = (xf – xi) / dx
‘ output initial condition
PRINT x, y
‘Loop to implement Euler’s method
‘and display results
DOFOR I = 1, nc
dydx = -(2X**3) + (12X**2) - (20X) + 8.5
y = y + dydx . dx
x = x + dx
PRINT x, y
END DO
I'm pretty sure that this pseudocode is what I need to implement, but I failed to convert it into Matlab code.
Any help please ?
I am not sure where you're failing, it would really help to know how you're failing or what's a complication. Otherwise this just seems like doing your homework.
Here's my attempt at the MATLAB code. (Note: I do not have MATLAB on this computer and have not tested it)
i = 0;
stepsize = .1; % Define as what you want it to be
y = 1; % Initial value condition given
t = 0; % Initial time value
yout = [zeros(1,20)]; % Assuming you want 20 outputs, can change
fvec = [zeros(1,20)];
for i = 1:20 % Time range, can change to correspond to what you want
fvec(i) = 2 - exp(-4*t) - 2*yout(i); % Just loops calculating based on Euler's method
yout(i+1) = yout(i) + stepsize*fvec(i)
t = t+stepsize % Time has passed, increment the time.
end
I'm not entirely sure this code, but it should give you an example of how to go about this. Please comment if something is wrong.