Issues with solving a quartic function analytically
6 views (last 30 days)
Show older comments
Dear all,
I'm solving for the variable "x" that is plugged into an optimizer, after it has been solved for. Because of the nature of the optimizer, I'm not able to use the "roots"-function. Because of this I opted to solve the 4th order polynomial analytically, with the following scheme, as can be found publically on Wikipedia:

I have implemented this as follows with the relevant part or the script below:
% func = ((x)^4) + (2*(UC)*((x)^3)) + (((UC)^2) + ((UT)^2))*((x)^2) - 1;
UC = [-8.848312431038208e-17];
UT = [0.550226217684170];
a = 1;
b = 2*(UC);
c = ( ((UC).^2) + ((UT).^2) );
d = 0;
e = -1;
D_0 = ((c).^2) - (3*b*d) + (12*a*e);
D_1 = 2*((c).^3) - (9*b.*c*d) + (27*((b).^2)*e) + (27*a*((d)^2)) - (72*a*c*e);
Q = ( (D_1 + sqrt(((D_1).^2) - 4*((D_0).^3) ) ) ./ 2).^(1/3);
p = ((8*a*c) - (3*((b).^2))) ./ (8*((a).^2));
q = (((b).^3) - (4*a*b.*c) + (8*((a).^2).*d)) / (8*((a).^3));
S = (1/2) * sqrt( ((-2/3).*p) + (1/(3*a)).*(Q + (D_0)./Q) );
x_1 = (-b/(4*a)) - S + (1/2)*sqrt((-4*((S).^2)) - (2*p) + (q./S));
x_2 = (-b/(4*a)) - S - (1/2)*sqrt((-4*((S).^2)) - (2*p) + (q./S));
x_3 = (-b/(4*a)) + S + (1/2)*sqrt((-4*((S).^2)) - (2*p) - (q./S));
x_4 = (-b/(4*a)) + S - (1/2)*sqrt((-4*((S).^2)) - (2*p) - (q./S));
x = [x_1 x_2 x_3 x_4]
I've cross-checked the script for a known function, however, for some values the script produces values that do not make any sense. I've noticed that this happens especially with either very large or small values, but as I figured still well within eps.
Example:
For UC = [-8.848312431038208e-17] and UT =[0.550226217684170],
x =
Columns 1 through 4
[-0.0000 + 0.3891i -0.0000 - 0.3891i 0.0000 + 0.3891i 0.0000 - 0.3891i]
whereas, checking the answer with "roots" reveals the correct answer, which is reflected by Wolframalpha.
x = roots([a b c d e])
x =
0.9274 + 0.0000i
-0.0000 + 1.0783i
-0.0000 - 1.0783i
-0.9274 + 0.0000i
Is anyone able to tell me whether Matlab rounds off, without me knowing it, or if there is something else that I'm not seeing. I have already checked the code multiple times, but cant seem to be able to find a mistake.
Thank you!
3 Comments
John D'Errico
on 13 Feb 2018
Edited: John D'Errico
on 13 Feb 2018
MATLAB does not "round off" without telling you. Of course, it does use double precision, so all computations are effectively "rounded off". But that is no different than what happens inside roots. With UC=1e-17 essentially, note that UC^2 is into floating point trash, so some computations will produce garbage.
For example, with the values that you are using:
((UC)^2) + ((UT)^2))
is identical to
((UT)^2))
when computed in double precision. Don't believe me? Try it.
UC = [-8.848312431038208e-17]; UT =[0.550226217684170];
UC^2 + UT^2 == UT^2
ans =
logical
1
More to the point is Matt's question, why do you think this will be usable in an optimizer when roots causes a problem?
Answers (1)
Yassine Damerdji
on 20 Apr 2022
Matlab "roots" function uses the eigenvalue decomposition to derives the roots. Eig function is an iterative procedure that derives the roots in descending order of magnitude. Differences with Ferrari analytical method could be a problem of roundoff errors.
0 Comments
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!