Newton's iteration for root finding - matlab

I am writing a function which implements Newton's iteration for root-finding on a scalar function, i.e., find x such that f(x)=0, and x_(n+1) = x_n - [f(x_n)/f'(x_n)].
f1 and f1prime are the handles to compute f and f', and x0 is an initial root estimate, and 'tol' is the toleratnce. I have to continue the iteration until either |f(x_n+1)| is less than tol or I have exceeded 10^5 iterations. And, the output of the function is x_n+1.
Also... f(x)=3x^4-5x^3-12x^2 where f'(x)=12x^3-15x^2-24x.
My current code is...
f1=#(x) 3*x^4 -5*x^3 - 12*x^2;
f1prime=#(x) 12*x^3-15*x^2-24*x;
n=0;
root=x0;
while abs(f1(x(n+1))<tol ||n>10^5
x(n+1)=x(n)-f1(x(n))/fprime(x(n));
n=n+1;
end
My code should pass this test suite, but it did not. What is the problem of the above code?
tol=1e-6;
f1=#(x) 3*x^4 -5*x^3 - 12*x^2;
f1prime=#(x) 12*x^3-15*x^2-24*x;
x0=-1;
root_correct = [-1.333333];
[root]=newtonRoot(f1,f1prime,x0,tol);
tol1=1e-4;
assert( abs(root-root_correct) < tol1 , ...
[ '\nYour output \n root = [' sprintf(' %d ',root) ']\n' ...
'Expected output \n root = [' sprintf(' %d ',root_correct) ']\n' ], ...
root,root_correct);

Your looping condition is not correct:
while abs(f1(x(n+1)) < tol || n>10^5
continues as long as the absolute value of f1 is less than tol and n is greater than 10^5. Both conditions are not valid in the first iteration, thus you do not even iterate Newtons method once.
Try:
while abs(f1(x(n+1)) > tol && n < 10^5

Related

Single point Bisection Method - f(x)=e^(-x) -x

I want to find the root of f(x)=e^(-x) -x using the bisection method for a single point. I Was given c = sgn f(a)(b − a) I will use this later on the main program and
So first of all I have the following program in MATLAB:
function [y] =f(x)
y=exp(-x)-x;
end
then for my sgn which is the wheather the f(x) is negative or positive:
function [z] =sgn(x)
w=f(x);
if (w>0)
z=1;
elseif(w==0)
z=0;
else
z=-1;
endif
end
So implementing these in my final program I have the following code:
function [root,i,e]=bisection_mod(a,b,tol)
a=-1;b=2;
i=0;
xold= a;
xnew=0;
tol = 10^(-8);
e = abs(xnew-xold);
sgn(f(a))
c=sgn(f(a))*(b-a)
while (abs(xnew-xold) > tol)
if (i>1)
xold = xnew;
endif
cc=c*sgn(f(xold));
par=(2^(i+1));
xnew = xold + cc./par
e = abs(xnew-xold)
i=i+1;
if (i>100)
break
endif
endwhile
i
root=xnew
endfunction
the root of the function im trying to examin is 0.567
but my program gives back 0.2246.
Could I have some info about what I’m doing wrong or some corrections to my code?
Just a couple of tiny mistakes:
Your sgn function is computing sgn(f(f(x)))! You give it f(x) as input, and the first thing you do inside is do f(x) again! remote it from inside the function, make w=x.
You are not updating xold for the first 2 iterations! The first skip is OK, but in the second iteration i==1, therefore the condition should read if (i>=1) or better if(i>0).

Bisection doesn't return a value

The function below, bisection, is supposed to find a root given three inputs: a function f, and an interval defined using the two parameters a and b. The intention is that the value of a and b are changed within the function to approach a common point, as long as their signs are different.
When I call my function like this:
bisection( #(x)x-1 ,-2,3)
no output is returned. What am I doing wrong?
function X = bisection(f,a,b)
if ge((f(a)*f(b)),0)
disp('Wrong')
return;
end
X = (a+b)/2;
while abs(X)>0.01
if f(X)*f(a)>0
X=a;
else
X=b;
end
end
Enter the Infinite!
Well done! You've written your first (and not last, believe me) infinite loop. The problem is threefold. Firstly your stop condition was abs(X) and should have been abs(f(X)) - you don't care for X to be zero, you want f(X) to be zeros. Secondly you don't update your your X correctly so your break condition is never hit (unless you are lucky to give this function symmetrical a,b bounds around the zero of the function). You could see this easily by adding a line like disp(f(X)); pause(0.5); somewhere in the while-loop.
In general try to avoid infinite loops with some explicit stop condition. In my code below I've put in the interaction limit past which the algorithm will just stop (it would be more elegant to catch that condition and warn the user of hitting the iteration limit...).
function x0 = bisection(f,a,b)
assert(f(a)*f(b)<0,'Invalid f(x) range. f(a)*f(b) >= 0');
tol = 0.00001; % Tolerance
iter_limit = 10000; % Limit of number of iterations
iter = 0;
x0 = (a+b)/2; % Midpoint
while abs(f(x0)) > tol && iter < iter_limit
if f(x0)*f(a) > 0
a = x0; % Zero to the right of the midpoint
else
b = x0; % Zero to the left
end
x0 = (a+b)/2; % Recalculate midpoint
iter = iter + 1;
end
end
This should work no problem with
f = #(x)x-1;
bisection(f,-2,3);
I get something like 0.999992370... which is within specified tolerance from the actual answer (1).

Is there any special rules for nesting if-statement in for-loop in MATLAB?

I am trying to create a signal and then build a discrete-time signal by sampling the CT signal I create first. Until the last for-loop, things work out fine but I need to take N samples seperated by T. Without an if statement, I am getting an index out-of-bounds error and I had to limit sampling within the duration of the signal. For some reason, my code goes into if statement once and no more, and for debugging, I am printing out the values both in if and out of if. Although the logical operation should be true for more than one iteration(printing statements will show the values), it just does not print the statements inside the if-statement. What's wrong here?
function x = myA2D(b,w,p,T,N)
%MYA2D description: Takes in parameters to construct the CT-sampled DT signal
%b,w,p are Mx1 vectors and it returns Nx1 vector.
timeSpace = 0:0.001:3*pi;
xConstT = zeros(size(timeSpace));
%Construct Xc(t) signal
for k = 1:size(b,1)
temp = b(k) .* cos(w(k).*timeSpace + p(k));
xConstT = xConstT + temp;
end
plot(xConstT);
%Sampling CT-Signal to build DT-signal
disp(strcat('xConstT size',int2str(size(xConstT))));**strong text**
x = zeros(N,1);
sizeConstT = size(xConstT);
for i = 0:N-1
index = i .* T .* 1000 + 1;
disp(strcat('indexoo=',int2str(index)));
disp(strcat('xConstSizeeee',int2str(sizeConstT)));
if index <= sizeConstT
disp(strcat('idx=',int2str(index)));
disp(strcat('xSize',int2str(sizeConstT)));
%x(i+1,1) = xConstT(index);
end
end
end
sizeConstT = size(xConstT); creates an 1x2 array so you compare a float to an array, and your code enters the if loop only if comparison to each element of the array is successful. This example illustrates the issue:
if 1 <= [1 12]; disp('one'); end % <- prints 'one'
if 2 <= [1 12]; disp('two'); end % <- prints nothing
Your code will work with sizeConstT = length(xConstT);

MatLab using Fixed Point method to find a root

I wanna find a root for the following function with an error less than 0.05%
f= 3*x*tan(x)=1
In the MatLab i've wrote that code to do so:
clc,close all
syms x;
x0 = 3.5
f= 3*x*tan(x)-1;
df = diff(f,x);
while (1)
x1 = 1 / 3*tan(x0)
%DIRV.. z= tan(x0)^2/3 + 1/3
er = (abs((x1 - x0)/x1))*100
if ( er <= 0.05)
break;
end
x0 = x1;
pause(1)
end
But It keeps running an infinite loop with error 200.00 I dunno why.
Don't use while true, as that's usually uncalled for and prone to getting stuck in infinite loops, like here. Simply set a limit on the while instead:
while er > 0.05
%//your code
end
Additionally, to prevent getting stuck in an infinite loop you can use an iteration counter and set a maximum number of iterations:
ItCount = 0;
MaxIt = 1e5; %// maximum 10,000 iterations
while er > 0.05 & ItCount<MaxIt
%//your code
ItCount=ItCount+1;
end
I see four points of discussion that I'll address separately:
Why does the error seemingly saturate at 200.0 and the loop continue infinitely?
The fixed-point iterator, as written in your code, is finding the root of f(x) = x - tan(x)/3; in other words, find a value of x at which the graphs of x and tan(x)/3 cross. The only point where this is true is 0. And, if you look at the value of the iterants, the value of x1 is approaching 0. Good.
The bad news is that you are also dividing by that value converging toward 0. While the value of x1 remains finite, in a floating point arithmetic sense, the division works but may become inaccurate, and er actually goes NaN after enough iterations because x1 underflowed below the smallest denormalized number in the IEEE-754 standard.
Why is er 200 before then? It is approximately 200 because the value of x1 is approximately 1/3 of the value of x0 since tan(x)/3 locally behaves as x/3 a la its Taylor Expansion about 0. And abs(1 - 3)*100 == 200.
Divisions-by-zero and relative orders-of-magnitude are why it is sometimes best to look at the absolute and relative error measures for both the values of the independent variable and function value. If need be, even putting an extremely (relatively) small finite, constant value in the denominator of the relative calculation isn't entirely a bad thing in my mind (I remember seeing it in some numerical recipe books), but that's just a band-aid for robustness's sake that typically hides a more serious error.
This convergence is far different compared to the Newton-Raphson iterations because it has absolutely no knowledge of slope and the fixed-point iteration will converge to wherever the fixed-point is (forgive the minor tautology), assuming it does converge. Unfortunately, if I remember correctly, fixed-point convergence is only guaranteed if the function is continuous in some measure, and tan(x) is not; therefore, convergence is not guaranteed since those pesky poles get in the way.
The function it appears you want to find the root of is f(x) = 3*x*tan(x)-1. A fixed-point iterator of that function would be x = 1/(3*tan(x)) or x = 1/3*cot(x), which is looking for the intersection of 3*tan(x) and 1/x. However, due to point number (2), those iterators still behave badly since they are discontinuous.
A slightly different iterator x = atan(1/(3*x)) should behave a lot better since small values of x will produce a finite value because atan(x) is continuous along the whole real line. The only drawback is that the domain of x is limited to the interval (-pi/2,pi/2), but if it converges, I think the restriction is worth it.
Lastly, for any similar future coding endeavors, I do highly recommend #Adriaan's advice. If would like a sort of compromise between the styles, most of my iterative functions are written with a semantic variable notDone like this:
iter = 0;
iterMax = 1E4;
tol = 0.05;
notDone = 0.05 < er & iter < iterMax;
while notDone
%//your code
iter = iter + 1;
notDone = 0.05 < er & iter < iterMax;
end
You can add flags and all that jazz, but that format is what I frequently use.
I believe that the code below achieves what you are after using Newton's method for the convergence. Please leave a comment if I have missed something.
% find x: 3*x*tan(x) = 1
f = #(x) 3*x*tan(x)-1;
dfdx = #(x) 3*tan(x)+3*x*sec(x)^2;
tolerance = 0.05; % your value?
perturbation = 1e-2;
converged = 1;
x = 3.5;
f_x = f(x);
% Use Newton s method to find the root
count = 0;
err = 10*tolerance; % something bigger than tolerance to start
while (err >= tolerance)
count = count + 1;
if (count > 1e3)
converged = 0;
disp('Did not converge.');
break;
end
x0 = x;
dfdx_x = dfdx(x);
if (dfdx_x ~= 0)
% Avoid division by zero
f_x = f(x);
x = x - f_x/dfdx_x;
else
% Perturb x and go back to top of while loop
x = x + perturbation;
continue;
end
err = (abs((x - x0)/x))*100;
end
if (converged)
disp(['Converged to ' num2str(x,'%10.8e') ' in ' num2str(count) ...
' iterations.']);
end

Solving for the square root by Newton's Method

yinitial = x
y_n approaches sqrt(x) as n->infinity
If theres an x input and tol input. Aslong as the |y^2-x| > tol is true compute the following equation of y=0.5*(y + x/y). How would I create a while loop that will stop when |y^2-x| <= tol. So every time through the loop the y value changes. In order to get this answer--->
>>sqrtx = sqRoot(25,100)
sqrtx =
7.4615
I wrote this so far:
function [sqrtx] = sqrRoot(x,tol)
n = 0;
x=0;%initialized variables
if x >=tol %skips all remaining code
return
end
while x <=tol
%code repeated during each loop
x = x+1 %counting code
end
That formula is using a modified version of Newton's method to determine the square root. y_n is the previous iteration and y_{n+1} is the current iteration. You just need to keep two variables for each, then when the criteria of tolerance is satisfied, you return the current iteration's output. You also are incrementing the wrong value. It should be n, not x. You also aren't computing the tolerance properly... read the question more carefully. You take the current iteration's output, square it, subtract with the desired value x, take the absolute value and see if the output is less than the tolerance.
Also, you need to make sure the tolerance is small. Specifying the tolerance to be 100 will probably not allow the algorithm to iterate and give you the right answer. It may also be useful to see how long it took to converge to the right answer. As such, return n as a second output to your function:
function [sqrtx,n] = sqrRoot(x,tol) %// Change
%// Counts total number of iterations
n = 0;
%// Initialize the previous and current value to the input
sqrtx = x;
sqrtx_prev = x;
%// Until the tolerance has been met...
while abs(sqrtx^2 - x) > tol
%// Compute the next guess of the square root
sqrtx = 0.5*(sqrtx_prev + (x/sqrtx_prev));
%// Increment the counter
n = n + 1;
%// Set for next iteration
sqrtx_prev = sqrtx;
end
Now, when I run this code with x=25 and tol=1e-10, I get this:
>> [sqrtx, n] = sqrRoot(25, 1e-10)
sqrtx =
5
n =
7
The square root of 25 is 5... at least that's what I remember from maths class back in the day. It also took 7 iterations to converge. Not bad.
Yes, that is exactly what you are supposed to do: Iterate using the equation for y_{n+1} over and over again.
In your code you should have a loop like
while abs(y^2 - x) > tol
%// Calculate new y from the formula
end
Also note that tol should be small, as told in the other answer. The parameter tol actually tells you how inaccurate you want your solution to be. Normally you want more or less accurate solutions, so you set tol to a value near zero.
The correct way to solve this..
function [sqrtx] = sqRoot(x,tol)
sqrtx = x;%output = x
while abs((sqrtx.^2) - x) > tol %logic expression to test when it should
end
sqrtx = 0.5*((sqrtx) + (x/sqrtx)); %while condition prove true calculate
end
end