Numerical calculation of functional root

Functional root of function g(x) is function f(x), such that:

f(f(x)) = g(x)

General solution of this problem may be obtained via Abel's equation. here I will show a numeric approach, based on tailor series.

In general case, using Tailor series is complicated, but problem becomes much more simple, if g(0)=0. (or, in more general case, if there exists a such that g(a)=a. In this case, substitution g1(x)=g(x+a)-a may be used)

Here is Taylor series for f(x) : f(f(x))=sin(x)

b=[1,0,-1,0,1,0,-1,0];b=[b,b,b];b=[b,b,b] derivs35 k=f./factorial(1:length(f)); 1 1 3 -8.33333333333333e-02 5 -6.25000000000000e-03 7 -1.31448412698413e-03 9 -3.20870535714286e-04 11 -7.25830038981081e-05 13 -9.30961590412545e-06 15 3.55278377180633e-06 17 3.61718730214484e-06 19 1.67771221103390e-06 21 3.74835625939595e-07 23 -9.90538181643828e-08 25 -1.19505318825601e-07 27 -2.41736426371567e-08 29 2.70861781928743e-08 31 1.79479210513537e-08 33 -7.50080741478029e-09 It gives error < 10-4 for |x| < 1.4 and < 10-16 for |x| < 0.6. For x=pi/2 error is about 1e-2..1e-3. Increasing number of elements does not increases convergence at 1.6 much.

More interesting thing is half-exponent: f(f(x))=ex. Exponent does not intersects line y=x, so Taylor approach cannot be used. But if we consider complex x and y, intersection exists (furthermore, there are infinite number of intersections).

These points ma be found using Lambert's W function:

a0=-lambertw(-1)

ans = 0.318131505204764 - 1.337235701430689i

Now let us shift to the point a0 and calculate Taylor series at this point: g(x) = ex + a0 - a0

All derivatives of g(x) at 0 are equal to ea0. therefore let's use algorhytm b=ones(1,35)*a0; derivs35 k=f./factorial(1:length(f)); plot(abs(k(1:end-1)./k(2:end))) %from this plot we can see convergence radius that is about 1.3, which is close to complex part of a0. axis([0,35,0,2.5]) Therefore, this series can not be used for calculation of half-exponent at real axis. Newertheless, let's try x=linspace(0,1,100);y=polyval([fliplr(k),0],x-a0)+a0;yy=polyval([fliplr(k),0],y-a0)+a0; plot(x,real(yy),x,imag(yy),x,exp(x)) axis([0,1,-0.5,2]) This graph shows that convergence is really bad, but at interval [0.2..0.7] results are adequate. Looks like f(x) is significantly non-real for real arguments, though it may be result of bad convergence. Besides, equation exp(x)=x has other solutions. Maybe, they give better series? Let us try. a0=-lambertw(1,-1) a0 = 2.06227772959828 - 7.58863117847251i Radius is about b=ones(1,35)*a0; derivs35 k=f./factorial(1:length(f)); Radius is about 8.2, but |a0| is about 7.8. Alas, convergense still bad.

Files

Python script for generating the derivs35.m file: derivs.py. Usage: python derivs.py > derivs35.m To change maximal order, find line N=35 in script and change it. Complexity grows almos exponentially, so more than 45 is probably impossible to calculate. Generated script itself (bziped): derivs35.m.bz2.derivs2.m.bz2derivs10.m.bz2 Usage: create aray named b, containing derivatives of g(x) at zero. For example, for sin(x): b=[1,0,-1,0];b=[b,b,b,b,b]; Then run derivs35. it will create array f, containing values of derivative of f(x) at zero. To get Taylor series of f(x), divide elements of f by n!: k=f./factorial(1:length(f)); To calculate value of function use polyval: y=polyval([fliplr(k),0],x);
Сайт управляется системой uCoz