
Find all roots of non linear equation
3 views (last 30 days)
Show older comments
Hi,
i want to find the all roots of an non linear equation without using the symbolic toolbox because of runtime issues. So i tried to use fzero and i found this helpful thread: https://de.mathworks.com/matlabcentral/answers/160117-how-to-use-fzero-and-choose-correctly-initial-guess
So i added my equation to it. The problem is that it doesn't fin initial guesses because of the step size. if i am using x = linspace(-1,1); it finds the root but not if i have a bigger intervall. And the problem is that normally i don't know the intervall that exactly.
1. Has sb an idea how i could improve the code to make it work for me ? Or has sb any idea how i could solve this problem with another method ? I cannot use roots() or sth else for polynoms because the equation is no polynom.
if true
b1=0
b2=0
v1=0
v2=0
s1=0
s2=0.175
j2=0.28
tau =300
x = linspace(-10,10); % Interval To Evaluate Over
f = @(x)-s2 + s1 + (v1 + (b1 - j2.*x).^2/(2.*j2) + (j2.*x.^2)/2 - (b1.*(b1 - j2.*x))/j2).*(tau - x - (2.*b2 - 2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2))/(2.*j2) + (b1 - j2.*x)/j2 + (2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2))/(2.*j2)) + (2.*b2 - 2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2)).^3/(48.*j2.^2) - (b1 - j2.*x).^3/(6.*j2.^2) + (j2.*x.^3)/3 + x.*(v1 + (b1 - j2.*x).^2/(2.*j2) - (b1.*(b1 - j2.*x))/j2) - (v1.*(b1 - j2.*x))/j2 + (2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(3/2))/(24.*j2.^2) + (b1.*(b1 - j2.*x).^2)/(2.*j2.^2) + ((2.*b2 - 2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2)).*(v1 - (j2.*v1 - j2.*v2 - b1.^2/2 + b2.^2/2 + j2.^2.*x.^2)/(2.*j2) + (b1 - j2.*x).^2/(2.*j2) + (j2.*x.^2)/2 - (b1.*(b1 - j2.*x))/j2))/(2.*j2) + (2.^(1/2).*(2.*b2 - 2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2)).^2.*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2))/(16.*j2.^2) - (2.^(1/2).*(v1 + (b1 - j2.*x).^2/(2.*j2) + (j2.*x.^2)/2 - (b1.*(b1 - j2.*x))/j2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2))/(2.*j2);
fplot(f)
fx = f(x); % Function Evaluated Over ‘x’
cs = fx.*circshift(fx,-1,2); % Product Negative At Zero-Crossings
xc = x(cs <= 0); % Values Of ‘x’ Near Zero Crossings
for k1 = 1:length(xc)
fz(k1) = fzero(f, xc(k1)); % Use ‘xc’ As Initial Zero Estimate
end
syms x
f = -s2 + s1 + (v1 + (b1 - j2.*x).^2/(2.*j2) + (j2.*x.^2)/2 - (b1.*(b1 - j2.*x))/j2).*(tau - x - (2.*b2 - 2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2))/(2.*j2) + (b1 - j2.*x)/j2 + (2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2))/(2.*j2)) + (2.*b2 - 2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2)).^3/(48.*j2.^2) - (b1 - j2.*x).^3/(6.*j2.^2) + (j2.*x.^3)/3 + x.*(v1 + (b1 - j2.*x).^2/(2.*j2) - (b1.*(b1 - j2.*x))/j2) - (v1.*(b1 - j2.*x))/j2 + (2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(3/2))/(24.*j2.^2) + (b1.*(b1 - j2.*x).^2)/(2.*j2.^2) + ((2.*b2 - 2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2)).*(v1 - (j2.*v1 - j2.*v2 - b1.^2/2 + b2.^2/2 + j2.^2.*x.^2)/(2.*j2) + (b1 - j2.*x).^2/(2.*j2) + (j2.*x.^2)/2 - (b1.*(b1 - j2.*x))/j2))/(2.*j2) + (2.^(1/2).*(2.*b2 - 2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2)).^2.*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2))/(16.*j2.^2) - (2.^(1/2).*(v1 + (b1 - j2.*x).^2/(2.*j2) + (j2.*x.^2)/2 - (b1.*(b1 - j2.*x))/j2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2))/(2.*j2);
vpa(solve(f,x))
end
6 Comments
Answers (3)
Star Strider
on 18 Jul 2018
That algorithm will work when the increment in your ‘x’ vector is small enough to detect the sign change.
The solution is to simply add more points to increase the resolution of the vector:
x = linspace(-10,10,1000); % Interval To Evaluate Over
that then produces:
fz =
-0.045636604654443 0.045643546458764
as desired, and acceptably close to the symbolic result.
6 Comments
Star Strider
on 19 Jul 2018
It could change. To search for more roots, increase the ‘k1’ limit, and provide new initial estimates:
for k1 = 1:4
[xv(k1,:),fxval(k1,:)] = fsolve(f, (-1/k1)*((-1)^k1)/tau); % Find Both Roots, Scale Initial Estimate By ‘1/tau’
end
xroots =
-0.010218893299935 + 0.395164734474393i
0.002137898025294 - 0.395703760614642i
-0.010218911868143 + 0.395164745783536i
0.002137898022517 - 0.395703760622581i
These (using your most recent set of constants) are acceptably close to the symbolic solve results.
The initial estimates are calculated as ‘(-1/k1)*((-1)^k1)/tau’.
Dimitris Kalogiros
on 18 Jul 2018
Dear IlPadrino
Your equation is not a "nonlinear" equation. If you try to search its roots fist at the interval [0, +inf) and then at (-inf, 0) , you can rid of this annoying square root.
Have a look at the following piece of code :
clear all;
clc;
% Initial problem
b1=0;
b2=0;
v1=0;
v2=0;
s1=0;
s2=0.175;
j2=0.28;
tau =300;
syms x
% initial form of f
f = -s2 + s1 + (v1 + (b1 - j2.*x).^2/(2.*j2) + (j2.*x.^2)/2 - (b1.*(b1 - j2.*x))/j2).*(tau - x - (2.*b2 - 2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2))/(2.*j2) + (b1 - j2.*x)/j2 + (2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2))/(2.*j2)) + (2.*b2 - 2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2)).^3/(48.*j2.^2) - (b1 - j2.*x).^3/(6.*j2.^2) + (j2.*x.^3)/3 + x.*(v1 + (b1 - j2.*x).^2/(2.*j2) - (b1.*(b1 - j2.*x))/j2) - (v1.*(b1 - j2.*x))/j2 + (2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(3/2))/(24.*j2.^2) + (b1.*(b1 - j2.*x).^2)/(2.*j2.^2) + ((2.*b2 - 2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2)).*(v1 - (j2.*v1 - j2.*v2 - b1.^2/2 + b2.^2/2 + j2.^2.*x.^2)/(2.*j2) + (b1 - j2.*x).^2/(2.*j2) + (j2.*x.^2)/2 - (b1.*(b1 - j2.*x))/j2))/(2.*j2) + (2.^(1/2).*(2.*b2 - 2.^(1/2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2)).^2.*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2))/(16.*j2.^2) - (2.^(1/2).*(v1 + (b1 - j2.*x).^2/(2.*j2) + (j2.*x.^2)/2 - (b1.*(b1 - j2.*x))/j2).*(2.*j2.*v1 - 2.*j2.*v2 - b1.^2 + b2.^2 + 2.*j2.^2.*x.^2).^(1/2))/(2.*j2)
%simplify f
f=expand(f)
% searching for roots at interval [0 +inf)
assume(x>=0);
f1=simplify(f)
sol_Right=solve(f1==0)
%searching for roots at (-inf , 0)
assume(x<0)
f2=simplify(f)
sol_left=vpasolve(f2==0)
% Graphical demonstration
fplot(f,[-.1 .1]); grid on; hold on; fplot(0,[-.1, .1]);
I've run this , and you can find results of it, inside the file I've attached.
2 Comments
James Tursa
on 18 Jul 2018
It certainly is nonlinear. I think what you meant to write is that with the proper interpretation it can be reduced to a polynomial.
Walter Roberson
on 19 Jul 2018
The solution involves the roots of a quartic.
P4 = -9*sqrt(2)*(-2*j2^2*tau^2+((-4*b1+4*b2)*tau-6*v1+6*v2)*j2+(b1+5*b2)*(b1-b2));
P3 = (72*tau*v2+72*s1-72*s2)*j2^2+((-72*v1+72*v2)*b1-36*b2^2*tau)*j2+24*b1^3-36*b1*b2^2+12*b2^3;
P2 = -(3*(-24*tau*(tau*v2+s1-s2)*j2^3+(((24*v1-48*v2)*tau-24*s1+24*s2)*b1+12*b2^2*tau^2+(24*tau*v2+24*s1-24*s2)*b2+36*(v1-v2)^2)*j2^2-(8*(tau*b1^2+(b2*tau+3*v1*(1/2)-3*v2*(1/2))*b1-(2*(b2*tau-9*v1*(1/4)+9*v2*(1/4)))*b2))*(b1-b2)*j2+(b1^2+10*b1*b2+13*b2^2)*(b1-b2)^2))*sqrt(2);
P1 = 0;
P0 = -sqrt(2)*(-72*(tau*v2+s1-s2)^2*j2^4+((144*(v1-v2))*(tau*v2+s1-s2)*b1+72*tau*(tau*v2+s1-s2)*b2^2-72*(v1-v2)^3)*j2^3+((-48*tau*v2-48*s1+48*s2)*b1^3+36*(v1-v2)^2*b1^2+72*b2^2*(-tau*v1+2*tau*v2+s1-s2)*b1-(18*(b2^2*tau^2+(4*v2*tau*(1/3)+4*s1*(1/3)-4*s2*(1/3))*b2+6*(v1-v2)^2))*b2^2)*j2^2-(6*(b1-b2))*((v1-v2)*b1^3-4*b2*(b2*tau-(1/4)*v1+(1/4)*v2)*b1^2-(4*(b2*tau+5*v1*(1/4)-5*v2*(1/4)))*b2^2*b1+(2*(b2*tau-9*v1*(1/2)+9*v2*(1/2)))*b2^3)*j2+(b1^4+2*b1^3*b2-10*b1*b2^3-11*b2^4)*(b1-b2)^2);
RRR = roots([P4, P3, P2, P1, P0]);
xroots = (3*RRR.^3*sqrt(2) + (12*tau*v2+12*s1-12*s2)*j2^2 + ((-12*v1+12*v2)*b1 - 6*b2^2*tau + 6*RRR.^2*tau)*j2 + 4*b1^3 + (6*RRR.^2-6*b2^2)*b1 + 2*b2^3 - 6*RRR.^2*b2) ./ (6*j2*((-2*v1+2*v2)*j2 + b1^2 - b2^2 + RRR.^2));
These are not guaranteed to be real-valued, and are not guaranteed to be unique.
9 Comments
See Also
Categories
Find more on Symbolic Math Toolbox in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!