function root finding by secant method in matlab - 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;

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

Newton Raphson method problem when iterating a variable

I need help with a problem. I written a program to calculate the value of a function using the Newton Raphson method. However, the function also has a variable i would like to iterate over, V. The program runs fine until the second iteration of the outer for loop, then the inner for loop will not run further once it reaches the Newton Raphson function. If someone has any ideas of what is wrong, I would greatly appreciate it. The error i get is: Warning: Solution does not exist because the system is inconsistent.
The code is below for detail.
for V = 1:50;
syms x;
f(V)= Il-x-Is.*(exp((q.*(V+x.*Rs))./(1000.*y.*K.*T))-1)-((V+x.*Rs)./Rsh);
g(V)=diff(f(V));
x0 = 0;
i = 1;
for i=1:10
f0=vpa(subs(f,x,x0));
f0_der=vpa(subs(g,x,x0));
y=x0-f0/f0_der; % Newton Raphson
x0=y;
end
end
Assuming you have a function defined like
func = #(x,V) V+x+exp(x);
There are plenty of options that avoid expensive symbolic calculations.
Firstly, making a vector of values of x0 using fzero and a for loop:
for V = 1:50
x0(V) = fzero(#(x) func(x,V),0);
end
Secondly, the same thing again but written as an anonymous function, so you can call x0(1.5) or x0(1:50):
x0 = #(V) arrayfun(#(s) fzero(#(x) func(x,s),0),V);
Finally, if you want to use ten steps of Newton's method and calculate the derivative symbolically (although this is not a great method),
syms y Vsym
g = matlabFunction(diff(func(y,Vsym),y),'Vars',[y Vsym]);
for V = 1:50
x0(V) = 0;
for i = 1:10
x0(V) = x0(V)-func(x0(V),V)/g(x0(V),V); % Newton Raphson
end
end
Which at least will be more efficient in the loops because it's just using anonymous functions.

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

Order of convergence Newton

Hello I have written this to determine a root using Newton's method. The algorithm works. I also tried to implement an Experimental order of convergence EOC. It also works but I get the result that the order of convergence for Newton's method is 1 when in fact it is 2.
function [x,y,eoc,k]=newnew(f,df,x0,xe,eps,kmax)
x = x0;
y = feval(f,x);
for m=1:kmax
z = -y/feval(df,x);
x = x + z;
y = feval(f,x);
k = m;
for n=m
Ek=abs(x-xe);
end
for n=m+1
Ekp=abs(x-xe);
end
eoc=log(Ek)/log(Ekp);
if abs(y)<eps
return
end
end
disp('no convergence');
end
what is wrong?
When you say Ek=abs(x-xe) and Exp=abs(x-xe), they are exactly the same thing! That's why eoc evaluates to 1 every time.
Notice that you have no n in those equations. In fact, you don't need those extra for n=m loops either. Inside the for m=1:kmax loop, m is a single value not an array.
eoc needs to be calculated by comparing the previous loop iteration to the current one (since it doesn't make much sense to compare to a future loop iteration which hasn't happened yet). Because this looks like homework, I won't give you any code.. but this is a very strong hint.

How to solve symbolic equation in matlab

I have an equation in Matlab according to X parameter . I want to find the amount of X for the random amounts of F(x) .
and I tried the code below . but It gives me two different results while my equation should have just one result .
even I tried the roots(f) instead of solve(f) but it gave me an error :
??? Undefined function or method 'isfinite' for input arguments of
type 'sym'.
anybody can help me in this ?
what should I do ?
even if I have a wrong idea about solving this problem please tell me .
Thank you
function betaDistribution_2(a,b)
syms x ;
y=inline((x^(a-1))*((1-x)^(b-1)));
beta=quad(y,0,1);
g=(1/beta)*(x^(a-1))*((1-x)^(b-1));
% I have this equation and I want to find the amount of x for the random
%amounts of p
p=int(g,x,0,x);
for i=0:50
fxi=rand(1);
f=p-fxi;
xi=solve(f);
result=eval(xi);
disp(result)
end
end
Try to filter your solutions.
a=1;
b=2;
% a threshold for imagery part
SMALL=1e-9;
syms x real;
y=inline((x^(a-1))*((1-x)^(b-1)));
beta=quad(y,0,1);
g=(1/beta)*(x^(a-1))*((1-x)^(b-1));
p=int(g,x,0,x);
% return true for physically meaningfull results
filter = #(xc) abs(imag(xc))<SMALL && real(xc)>0 && subs(g, x, xc) > 0 && subs(p, x, xc)>0;
for m=0:50
fxi=rand(1);
f=p-fxi;
xi=solve(f, x);
result=eval(xi);
idx = arrayfun (filter, result);
result = result(idx);
% make sure it is OK
assert(length(result)==1);
disp(result)
end