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

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).

Related

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).

This if is not working on Octave/Matlab

I have the code divided on three functions:
f.m (This function works)
function y=f(x)
y = x^2;
endfunction
df.m (The function that return the derivate of y=x^2. This function works)
function y=df(i)
syms x,diff(f(x),x);
subs(ans,x,i);
y = ans;
endfunction
newton.m (maxIt = max of tries)
function [x1,nIt] = newton (f,df,x0,tol,maxIt)
k=0;
x=x0;
nIt = 0;
while (k<maxIt)
if(df(x)== 0)
fprintf("La derivada, da resultado 0");
k=maxIt;
else
i = x - (f(x)/df(x))
x = i;
nIt = nIt + 1
k=k+1;
endif
end
endfunction
Ok, I executed the command newton(#f,#df,0,10,2). Two-thirds of the program works OK, but if I do df(0), the result is 0 but the if doesn't work. I verified that df(0) returns 0, and it's OK.
I´m new in MATLAB/Octave.
You have several mistakes in your code. Not all of them are directly relevant, but fixing all of them will make your code more readable and robust.
The function f if fine.
The function df assumes that f is known somehow, but it's not a good practice. you better pass f too to this function. Also, don't use ans as a variable, store your intermediate result in different variables. This is how df should look:
function y = df(f,a)
syms x
d = diff(f(x),x);
y = subs(d,x,a);
end
Now you have to change all the calls to df in your newton function to df(f,x). I'm not sure what is your final goal, but right now, the variables x1 and tol are not in use in any way.
Hope it solves the problem ;)

function root finding by secant method in matlab

I have this matlab code for calculating the root of a function by using secant method :
syms x
f=#(x) x.^2-2;
x0=1;
x1=5;
tol=0.01;
for i=1:100
if (f(x0)-f(x1)) < 0.00001
break;
end
xn = x0-((f(x0)*(x0-x1))/(f(x0)-f(x1)));
if abs(xn-x0) < tol*abs(xn)
break;
end
x0=xn;
x1=x0;
end
fprintf('the root is %g\n', xn)
When I run the code , matlab says : Undefined function or variable 'xn'.
Why it says that ? I did define the xn in the code !!!
thank you very much
You are missing an absolute value in this if statement:
if abs(f(x0)-f(x1)) < 0.00001
break;
end
Without this, the for loop breaks before you get to your xn definition, not because f(x0) is close to f(x1), but because the result is negative.
Running it through, you have a second problem, these lines need to be swapped around, otherwise they end up being equal, which is not what you want.
x0=xn;
x1=x0;

Newton's iteration for root finding

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

Matlab: Optimizing speed of function call and cosine sign-finding in a loop

The code in question is here:
function k = whileloop(odefun,args)
...
while (sign(costheta) == originalsign)
y=y(:) + odefun(0,y(:),vars,param)*(dt); % Line 4
costheta = dot(y-normpt,normvec);
k = k + 1;
end
...
end
and to clarify, odefun is F1.m, an m-file of mine. I pass it into the function that contains this while-loop. It's something like whileloop(#F1,args). Line 4 in the code-block above is the Euler method.
The reason I'm using a while-loop is because I want to trigger upon the vector "y" crossing a plane defined by a point, "normpt", and the vector normal to the plane, "normvec".
Is there an easy change to this code that will speed it up dramatically? Should I attempt learning how to make mex files instead (for a speed increase)?
Edit:
Here is a rushed attempt at an example of what one could try to test with. I have not debugged this. It is to give you an idea:
%Save the following 3 lines in an m-file named "F1.m"
function ydot = F1(placeholder1,y,placeholder2,placeholder3)
ydot = y/10;
end
%Run the following:
dt = 1.5e-12 %I do not know about this. You will have to experiment.
y0 = [.1,.1,.1];
normpt = [3,3,3];
normvec = [1,1,1];
originalsign = sign(dot(y0-normpt,normvec));
costheta = originalsign;
y = y0;
k = 0;
while (sign(costheta) == originalsign)
y=y(:) + F1(0,y(:),0,0)*(dt); % Line 4
costheta = dot(y-normpt,normvec);
k = k + 1;
end
disp(k);
dt should be sufficiently small that it takes hundreds of thousands of iterations to trigger.
Assume I must use the Euler method. I have a stochastic differential equation with state-dependent noise if you are curious as to why I tell you to take such an assumption.
I would focus on your actual ODE integration. The fewer steps you have to take, the faster the loop will run. I would only worry about the speed of the sign check after you've optimized the actual integration method.
It looks like you're using the first-order explicit Euler method. Have you tried a higher-order integrator or an implicit method? Often you can increase the time step significantly.