but I cannot get a solution. x is the variable, a and c are parameters. From “plot” I can tell there is one solution. Could anybody suggest the best way to get the root in this case? Solve, NSolve, Reduce and Root would generate the same Warning " This system cannot be solved with the methods available to …"
Hi,
thanks for your answer. However I rather need an analytical solution (or an approximation of it), as I am going to use the solution at run-time afterwards. Replacing a Taylor expansion of the equation doesn’t seem to solve the problem, as Mathematica doesn’t output the root: it is clearly one per (x,a) looking at the plot. An idea I had to overcome the problem is to generate sample points x^a-a*Log[1-x] with 1/2<x<1&&0<a<1 and then try to fit it. Replace the function with the fitted function and hopefully I get an equation, which is easier to solve. Well, I don’t know if it is the best solution to this problem and actually I cannot do it: I am currently investigation how to get it on the web.
Can’t you represent the power x^a as a logarithmic expression to homogenize the look of the equation? Have you tried all flavours of simplify on the equation, to get some idea where to find the next step?
I tried Simplify[x^a-a*Log[1-x]-c==0,1/2<=x<=1&&Element[x,Reals]&&0<a<1&&Element[a,Reals]&&Element[c,Reals]] but doesn’t really simplify (or change at all) the equation. I find tricky that in one term there is logarithm and in the other power as well as in on term x and in the other 1-x. Then, x=sin^2(theta) doesn’t really help …
maybe this simple (an hopefully not too stupid) idea is helpful: Using Newtons method with analytic expressions!
Define your function and the Newton iteration step:
f[x_] := x^a Log[1 - x] - c
newton[x_] := x - f[x]/f'[x]
Then you do some (not too many, e.g. 3) interations:
sol[x_] = Nest[newton, x, 3];
This results in a large/huge - but analytical ! - formula.
Since you decided to have 1/2 < x < 1 you can start with an initial value for e.g. x=0.75; an approximation of the solution then should be (depending on the parameters a and c) as an example:
I know you want an analytic expression but if all of your future calculations are within Mathematica, why not use interpolation functions? (Or, is the need for an analytic expression so that you can use the results outside of Mathematica?)
n = 100; (* Number of elements in each row of the interpolation table \
*)
(* Set ranges for a and x *)
amin = 0.;
amax = 1.;
xmin = 0.5;
xmax = 1.;
(* Create table of values of a, c, and x *)
t = Flatten[
Table[{{amin + (amax - amin) i/
n, (xmin + (xmax - xmin) j/n)^(amin + (amax - amin) i/
n) - (amin + (amax - amin) i/n)*
Log[1 - (xmin + (xmax - xmin) j/n)]},
xmin + (xmax - xmin) j/n}, {i, 1, n}, {j, 1, n - 1}], 1];
(* Create interpolation function *)
f = Interpolation[t, InterpolationOrder -> 1]
(* Contour plot *)
ContourPlot[f[a, c], {a, 0.01, 0.99}, {c, 1.01, 6}]
(* Any particular point: f[a,c] *)
f[0.75, 2]
we’getting there … thanks for your suggestion The Newton’s method is working nicely for some values of (x,a). However, sometimes the provided solution is complex and the comparison to the attended values get bad. Would you have suggestion on how to restrict the Newton’s method to reals?
thanks for your help. I’ve just noticed the complex numbers come when I evaluate the Newton’s method too far away from the actual solution. This brings the story to the original problem, because I need to know where the solution roughly is before getting an analytical expression of it. Outside Mathematica the solution should be used often, so I might need a different approach to get one analytical expression to be quickly used.
I think the complex values show up when x<0. This typically happens when there is no solution at all (e.g. when c>0).
Have you ever encountered a complex “solution” when there definitely is a zero crossing?
One searches for a y satisfying the equation x^a=-a \log(1-y)
In[16]:= Solve[x^a == -a Log[1 - y] && 0 < a < 1 && 1/2 < x < 1, y, Reals]
Out[16]= {{y -> ConditionalExpression[1 - E^(-(x^a/a)), 0 < a < 1 && 1/2 < x < 1]}}
that’s trivial but allows to transform the equation into (1-x)\exp\left(-\frac{x^a}{a}\right)=\exp\left(-\frac{c}{a}\right). This will not be solved again
Solve[(1 - x) Exp[-x^a/a] == Exp[-c/a] && 1/2 < x < 1 && 0 < a < 1, x, Reals]
Solve::nsmet: This system cannot be solved with the methods available to Solve. >>
but can be expressed as (1-x)\exp\left(\frac{c-x^a}{a}\right)=1.
It’s interesting to see how different quality the corresponding ContourPlot3D for the three equivalent equations are.
Any derivative of the above mentioned expression must vanish, but I do not see an usage of that fact.
But one could try to develop around a = 1. At least for a=1 a solution appears
In[36]:= Solve[(1 - x) Exp[c - x] == 1 , x]
During evaluation of In[36]:= Solve::ifun: Inverse functions are being used by Solve, so some solutions may not be found; use Reduce for complete solution information. >>
Out[36]= {{x -> 1 - ProductLog[E^(1 - c)]}}
Solve[E^((c - x^a)/a) (1 - x) == 1, a]
Solve::nsmet: This system cannot be solved with the methods available to Solve. >>
of course.
You could solve
In[47]:= Solve[E^((c - x^a)/a) (c - x^a)/a == 1, x]
During evaluation of In[47]:= Solve::ifun: Inverse functions are being used by Solve, so some solutions may not be found; use Reduce for complete solution information. >>
Out[47]= {{x -> (c - a ProductLog[1])^(1/a)}}
but again no benefit from this information is visible.
I think the solution for you (as you need a good algorithm for the outside world - C? Fortran? Basic? Perl?) will ultimately depend on what values of c and a you expect and how precise you want to be able to determine x.
From everything folks have mentioned above:
c must be greater than or equal to 1.19315 (as 0.5 < x < 1).
For any value of c the minimum value of x will be when a = 1. This will give you a lower limit for x in any search algorithm. You can use what Udo Krause mentioned to find that lower limit.
If you only need to know x up to 0.9999, then you won’t need to perform any iterative method if c is greater than about 10. You just return 0.9999 or 1.0000.
Also, because c is linearly related to a for a given value of x, if there is some maximum x like 0.9999, then one can determine if the (c,a) pair is above the line for x = 0.9999 which the function could then return 0.9999 if that was your upper threshold for x.
Depending on the precision desired for x, you might need to consider multiple precision support as double precision might not give enough precision. When c = 100, then the maximum value of x is 0.99999999999999999999999999999999999999999989887785073895514700547142\ 0237974134503800561929733764673745574785011843276329550445380987673228\ 2904164154378408341327050646705054851432685561291692934129708640969732\ 9364105768971523513419413703741965175554141229402839267590651808760914\ 99111583603367054544515.
. I don’t think that double-precision will get you there (unless maybe there’s merit in finding 1 - x).
For more numeric stability I rearranged x^a - a Log[1-x] == c to x == 1 - Exp[(x^a - c)/a]. Using a starting value of 1:
f[a_, c_, n_: 20] := Module[{z, i},
(* n is number of iterations *)
z = 1;
Do[
z = 1 - Exp[(z^a - c)/a],
{i, n}];
z]
(* Example *)
a = 0.5;
c = 10;
x = f[a, c]
(* Check: the value below should be close to zero *)
If[x < 1, x^a - a Log[1 - x] - c, "Estimate is too close to 1"]
(* Use FindRoot now that we hopefully have a good starting value *)
FindRoot[z^a - a Log[1 - z] == c, {z, x}]
When the desired result is too close to 1, then things don’t work so well. If you get a solution less than 0.9999, you’re probably safe. Using variables with higher than double precision would also help. Again, because of the linear relationship of a and c for a specific value of x, one could determine if the result will be bigger than some safe threshold like maybe 0.9999.
If you need to know if x is something like 0.99999999994, then you’d absolutely need multiple precision arithmetic for your “outside” program.
Let’s set a=1/2, because of 1=(1-x)\exp\left(\frac{c-x^a}{a}\right) one could ask for the fourier transform. The 1 goes to the dirac delta , but
In[64]:= (* a = 1/2 *)
FourierTransform[E^(2 (c - Sqrt[x])) (1 - x), x, w]
Out[64]= (1/(8 Sqrt[2 \[Pi]] w^4 Abs[w]^(9/2)))E^(
2 c - I/w) (-2 I E^(2 I/w) Sqrt[2 \[Pi]] w^5 (2 - 3 I w + 2 w^2) +
Sqrt[2 \[Pi]]
w^4 (-3 I w + E^(2 I/w) (4 - 3 I w + 4 w^2)) Abs[w] -
3 I (-1 + E^(2 I/w)) Sqrt[2 \[Pi]] w^3 Abs[w]^3 +
4 E^(I/w) Abs[w]^(
9/2) (E^(I/w) Sqrt[\[Pi]] Sqrt[I w] (2 I + 3 w + 2 I w^2) -
2 I w (1 - I w + w^2) +
E^(I/w) Sqrt[\[Pi]] Sqrt[
I w] (2 - 3 I w + 2 w^2) Erfi[1/Sqrt[I w]]) +
32 I E^(I/w) w^5 Sqrt[Abs[w]]
HypergeometricPFQ[{2}, {3/4, 5/4}, -(1/(4 w^2))] +
8 E^(I/w) w^4 Abs[w]^(
5/2) (I w HypergeometricPFQ[{1}, {1/4, 3/4}, -(1/(4 w^2))] -
2 HypergeometricPFQ[{1}, {3/4, 5/4}, -(1/(4 w^2))] +
HypergeometricPFQ[{1, 3/2}, {1/4, 1/2, 3/4}, -(1/(4 w^2))]))
no chance to solve for w and to transform back. You need a truly clever trick to transform the condition or a numerical procedure along the lines Jim Baldwin proposed.