From: Themis Matsoukas on
I have a cubic polynomial in z (ZEQ) that depends on a parameter p. The polynomial has three real roots when p is in the interval (p1, p2). I then define function F[X] to be the ratio of the Max-to-Min (real) roots of ZEQ when p has the value X. Of course, F[X] makes sense only when ZEQ has three real roots, which restricts p to be in the interval p1<p<p2.

The problem: while F[X] is evaluated (and plotted) correctly, if I try to solve for, say F[X]=6, I get a wrong answer (the correct answer is X=0.4). I suspect the problem is that Mathematica does not restrict the evaluation of F[X] within the interval (p1,p2). If I don't want to write my own routine for the root, is there a way to restrict FindRoot to work only inside the interval (p1, p2)?

ZEQ=-0.049973 p^2+(0.44137p-0.00873 p^2) z-z^2+z^3;
{p1,p2}={0.133652,0.690323};
F[X_]:=(
z123=Sort[z/.Solve[(ZEQ/.p->X)==0,z]];
z123[[3]]/z123[[2]]
);

FindRoot[F[X]-6, {X, 0.40}]
F[X/.%]-6
{X->0.586195-5.08604*10^-16 I}
-3.40038

TableForm[Table[{X, F[X]-6}, {X, 0.38, 0.42, 0.01}]]
0.38 0.55303
0.39 0.266973
0.40 -0.00436745
0.41 -0.262155
0.42 -0.50744



Thanks

Themis

From: Bill Rowe on
On 7/20/10 at 3:43 AM, tmatsoukas(a)me.com (Themis Matsoukas) wrote:

>I have a cubic polynomial in z (ZEQ) that depends on a
>parameter p. The polynomial has three real roots when p is in
>the interval (p1,
>p2). I then define function F[X] to be the ratio of the Max-to-Min
>(real) roots of ZEQ when p has the value X. Of course, F[X] makes
>sense only when ZEQ has three real roots, which restricts p to be in
>the interval p1<p<p2.

>The problem: while F[X] is evaluated (and plotted) correctly, if I
>try to solve for, say F[X]=6, I get a wrong answer (the correct
>answer is X=0.4). I suspect the problem is that Mathematica does not
>restrict the evaluation of F[X] within the interval (p1,p2). If I
>don't want to write my own routine for the root, is there a way to
>restrict FindRoot to work only inside the interval (p1, p2)?

>ZEQ=-0.049973 p^2+(0.44137p-0.00873 p^2) z-z^2+z^3;
>{p1,p2}={0.133652,0.690323};
>F[X_]:=(
>z123=Sort[z/.Solve[(ZEQ/.p->X)==0,z]];
>z123[[3]]/z123[[2]]
>);

>FindRoot[F[X]-6, {X, 0.40}]
>F[X/.%]-6
>{X->0.586195-5.08604*10^-16 I}
>-3.40038

Yes, it is possible to restrict the range over which FindRoot
works. By doing

FindRoot[F[x]-6,{x,0.4,p1,p2}]

But, restricting the range for x doesn't seem to be enough to
allow FindRoot to get the desired solution. The problem seems to
be your ZEQ is numerically unstable. Note the difference between

In[18]:= F[.4] - 6

Out[18]= -0.00436745

and

In[19]:= F[x] - 6 /. x -> .4

Out[19]= 4.34196-1.48672*10^-14 I

With this last, Solve will generate an error message indicating
it was unable to find a solution with inexact coefficients.

Additionally, if you do

F[x]

and look at the coefficients you will see there are approximate
numbers with both quite large and quite small absolute values.
That is, you will get different results due to issues with
machine precision arithmetic when making substitutions for the
variables in different ways.

Finally, the plot

Plot[F[x] - 6, {x, .399, .401}]

indicates the root is somewhat less than 0.4. But given the
apparent numerical instability for this particular problem, I am
not certain this result is more accurate than another result.


From: Themis Matsoukas on
Bill,

Your answer pointed me to the explanation for the wrong behavior, which I think is a bug in Mathematica. The clue is that F[X/.X->XX] and F[X]/.X->XX give different answers and the reason is that Mathematica's internal representation of F[X] as an analytic function of X is wrong. In the definition of F[X], the roots of the cubic are first sorted, then the function returns the ratio of root #3 to root #2 (in my original example I meant to use root #1 instead of #2 but this doesn't matter for the purposes of debugging). Apparently, the analytic form of F[X] (i.e. what you get when you execute X =.; F[X]]) does not sort the roots and instead takes the ratio of the wrong pair. At least, that's what the demo below shows.

With F[X /. X -> 0.3], F is evaluated according to its definition at a specified numerical value of X and returns the correct answer (a number). With F[X]/.X->.3 a different thing happens: first, the definition of F is executed for a symbolic X and returns a symbolic expression for F in terms of X, which however is wrong; then the analytic form is evaluated at the specified value of X.

The bottom line is this: F[X] is correct as long as X is a number; if it is an unevaluated symbol the answer is wrong. For this reason Plot, Table etc work but FindRoot, D, Integrate, etc do not. I would call this a bug in Mathematica since it produces an analytic expression for F that does not respect its definition and leads to apparent conflict between what should be equivalent representations, F[/.X->XX] and F[X]/.X->XX.

ZEQ=-0.049973 p^2+(0.44137p-0.00873 p^2) z-z^2+z^3;
{p1,p2}={0.133652,0.690320};
F[X_]:=(
z123=Sort[z/.Solve[(ZEQ/.p->X)==0,z]];
z123[[3]]/z123[[2]]);

XX=p1;
dX=(p2-p1)/3.;
imax=3;
results={};
Do[
roots=Sort[z/.Solve[(ZEQ/.p->XX)==0,z]];
results=Append[results, Join[{XX}, roots, {F[XX], Re[F[X]/.X->XX]}]];
XX=XX+dX;
,{i,1,imax+1}
];
TableForm[results, TableHeadings->{None,{"XX", "z1", "z2", "z3","F[X]", "Re[F[X]/.X->XX]"}}]

Themis