Ceros de la función exponencial

Etiquetas: Funciones de variable compleja , Comportamiento asintótico

(English: Zeros of the Exponential Function)

En 2012, creé la siguiente animación que muestra los ceros complejos de los polinomios de Taylor de la función exponencial $e^z$. En esta entrada, explicaré qué significa y por qué es interesante.

También mostraré el código en Sage para recrear la animación (que originalmente creé en Mathematica en 2012). A diferencia de Mathematica, que no es gratuito ni de código abierto, Sage es un sistema de software matemático de código abierto basado en Python que se construye sobre muchos paquetes de código abierto existentes.

¡Empecemos!

Visualizar números complejos

Los números complejos son números de la forma $$2+3i,\quad\text{o}\quad -1+\sqrt{2}i,\quad\text{o}\quad 1-5i$$ en donde $i=\sqrt{-1}$. Una forma de pensar en los números complejos es considerarlos como “números 2D”. La parte sin la $i$ nos dice la coordenada horizontal (parte real) y la parte con la $i$ nos dice la coordenada vertical (parte imaginaria), como en la imagen:

Ejemplos de números complejos.

Ejemplos de números complejos.

La función exponencial compleja

La función exponencial compleja $e^z$ extiende la función exponencial $e^x$ al permitir que la entrada $x$ sea un número complejo $z$.

Por ejemplo, redondeando, $$e^{2-3i}=-7.315-1.0427i.$$

Otro ejemplo es $$e^{\pi i}=-1.$$ Esta última igualdad es tan sorprendente que todavía la llamamos “la identidad de Euler” en honor al matemático que la descubrió alrededor de 1740. Leonhard Euler no solo la descubrió, sino que desarrolló la notación para que podamos escribirla. Más información aquí.

Para entender la animación, lo único que necesitamos saber sobre $e^z$ es que se puede escribir como una suma infinita (técnicamente conocida como serie de Taylor): $$ e^z=1+z+\frac{z^2}{2!}+\frac{z^3}{3!}+\frac{z^4}{4!}+\frac{z^5}{5!}+\ldots $$ En esta fórmula:

  • El “$!$” significa multiplicar por todos los números menores. Por ejemplo, $4!=4\times3\times2\times 1$.

  • La suma infinita significa que sumamos más y más términos esperando acercarnos a un valor. Ese valor es la suma. A veces funciona, como para $e^z$, y a veces no, como para $1+2+3+4+\ldots$.

Por ejemplo, para encontrar el valor de $e^z$ cuando $z=2$, sumamos más y más términos para acercarnos cada vez más a $$e^2=7.3890561\ldots,$$ así: $$ \begin{aligned} 1 & = 1\\ 1+2 & = 3\\ 1+2+\frac{2^2}{2!} & = 5\\ 1+2+\frac{2^2}{2!}+\frac{2^3}{3!} & = 6.333333…\\ 1+2+\frac{2^2}{2!}+\frac{2^3}{3!}+\frac{2^4}{4!} & = 7\\ 1+2+\frac{2^2}{2!}+\frac{2^3}{3!}+\frac{2^4}{4!}+\frac{2^5}{5!} & = 7.266666666….\\ 1+2+\frac{2^2}{2!}+\frac{2^3}{3!}+\frac{2^4}{4!}+\frac{2^5}{5!} +\ldots+ \frac{2^8}{8!} & = 7.38095238095238…\\ 1+2+\frac{2^2}{2!}+\frac{2^3}{3!}+\frac{2^4}{4!}+\frac{2^5}{5!} +\ldots+ \frac{2^{12}}{12!} & = 7.38904601571268…\\ 1+2+\frac{2^2}{2!}+\frac{2^3}{3!}+\frac{2^4}{4!}+\frac{2^5}{5!} +\ldots+ \frac{2^{20}}{20!} & = 7.38905609893017… \end{aligned} $$

Puede leer más sobre $e^z$ en el artículo de Wikipedia sobre la fórmula de Euler.

Los polinomios de Taylor de $e^z$ y sus ceros

El polinomio de Taylor de orden $n$ de $e^z$ se obtiene sumando solo hasta el término con $z^n$ en la serie de Taylor:

$$p_n(z) = 1+z+\frac{z^2}{2!}+\frac{z^3}{3!}+\ldots+\frac{z^n}{n!}.$$

Los polinomios $p_n(z)$ son aproximaciones de $e^z$ que mejoran a medida que $n$ aumenta.

El polinomio $p_n(z)$ tiene $n$ ceros complejos, que son las soluciones de la ecuación $p_n(z) = 0$. (Cualquier polinomio de grado $n$ tiene exactamente $n$ ceros complejos. Este hecho es tan importante que se llama “el Teorema Fundamental del Álgebra”).

Estos son los ceros para $n=3$ (como era de esperar, se ven 3 puntos: los 3 números complejos que satisfacen $p_3(z)=0$)

Y estos son los ceros para $n=5$ (como era de esperar, vemos 5 puntos)

Y estos son los ceros para $n=20$. ¡Interesante, se ven muy organizados!

Cómo se hicieron estas imágenes

Este es el código en Sage que escribí para producir una de estas imágenes, para un valor específico de $n$.

from sage.plot.colors import blue

# Value of n
n=20

# build p_n(z). Gets stored in f
f=0
for i in range(n+1):
    f=f+x^i/factorial(i)
    
# Find roots of f
roots=f.solve(x,to_poly_solve=True)  # to_poly_solve makes Sage use Maxima's solver package to find ALL the roots
numRoots=len(roots) # should be equal to n!
myRoots= [roots[i].right() for i in range(numRoots)]

# Plot the roots of f
myPlot=list_plot(
        [(real(i), imag(i)) for i in myRoots],
        xmin=-Integer(20),
        xmax=Integer(20),
        aspect_ratio=Integer(1),
        color=blue)
show(myPlot)

Encontrar los $n$ ceros complejos de un polinomio con precisión y velocidad para valores grandes de $n$ requiere ideas ingeniosas. Sage utiliza Maxima para estimar las raíces. Maxima es un sistema de álgebra simbólica de código abierto del MIT que ha estado en desarrollo desde la década de 1960.

Para guardar la imagen como un png, tan solo hay que usar el comando save:

myPlot.save("myFilename.png", dpi=200)

La animación

Esta es la animación de los ceros de $p_n(z)$ a medida que $n$ aumenta.

Con esto logramos el objetivo de esta entrada de blog: entender la animación del inicio y recrearla esta vez con Sage y con una resolución más alta.

Por qué la animación es interesante: $e^z$ no tiene ceros en el plano complejo, pero sus polinomios de Taylor tienen $n$ ceros.

  • ¿Cómo puede ser eso?
  • ¿Qué pasa con los ceros?

La animación muestra cómo los ceros escapan al infinito de una manera muy ordenada a medida que $n$ crece.

Cómo se producen las imágenes que componen la animación con Sage

El siguiente código de Sage crea las imágenes sagePngs/frame001.png, sagePngs/frame002.png, hasta sagePngs/frame050.png, cada una mostrando los ceros del polinomio de Taylor correspondiente. Estos png son las imágenes que conforman la animación.

from sage.plot.colors import blue
f=0
n=50
folder="sagePngs"
myPlot=Graphics()
for i in range(n+1):
    f=f+x^i/factorial(i)
    roots=f.solve(x,to_poly_solve=True)  # to_poly_solve makes Sage use Maxima's solver package to find ALL the roots
    numRoots=len(roots)
    myRoots= [roots[i].right() for i in range(numRoots)]
    filename=folder+"/"+"frame"+Integer(i).str().zfill(3)+".png"
    show("saved: "+filename)
    p=list_plot(
        [(real(root), imag(root)) for root in myRoots], 
        xmin=-Integer(20), 
        xmax=Integer(20), 
        ymin=-Integer(20), 
        ymax=Integer(20), 
        aspect_ratio=Integer(1), 
        color=blue)
    p.save(filename, dpi=200)

Este código es muy similar al código para crear la imagen de los ceros para un solo $n$. Simplemente se ajustó el código para crear una imagen y guardarla como un png en cada paso del ciclo en el que se construye $p_n$.

Con esos png se puede producir una animación usando Image Magick.

Crear el gif con Image Magick

Para poder ejecutar Image Magick en la terminal de MacOS se debe:

  • Instalar el fantástico Homebrew. Instrucciones en su sitio web.
  • Instalar el también fantástico ImageMagick desde la terminal con el comando:
brew install imagemagick

Una vez que se tiene Image Magick, es muy sencillo crear la animación. Simplemente se ejecuta en la terminal el siguiente comando:

convert frame*.png movie.gif

Para controlar la velocidad, se puede que agregar -delay X antes frame*.png con un valor de X. También se puede agregar -loop 0 antes del movie.gif para indicar cuántas veces debe repetirse (0 significa que nunca debe dejar de repetirse). El comando queda así:

convert -delay 20 frame*.png -loop 0 movie.gif

La estructura de fondo: curva de Szegő

Hay muchas cosas interesantes que se pueden explorar a partir de la animación. Por ejemplo, los ceros parecen formar una “onda” que crece alejándose del origen.

¿Podemos decir algo sobre su forma?

Esta pregunta fue respondida por Gábor Szegő en 1924, ¡sin computadoras!

Szegő descubrió que la forma correcta de evitar que los ceros se alejen al infinito es escalarlos por un factor de $n$. Cuando uno hace esto, los ceros convergen a una curva en forma de “lágrima”.

Esta está la animación con los factores de escala, con $n$ entre $1$ y $60$ (después de $n=60$, Sage tiene problemas para encontrar todos los ceros numéricamente).

¡Tanto orden oculto!

Szegő incluso encontró una fórmula para la curva límite. Es: $$ \left|ze^{1-z}\right|=1,\quad\text{para } |z|\leq 1 $$

y esta está su gráfica (la ecuación cartesiana es $x^{2}+y^{2}=e^{2(x-1)}$)

Código Sage para la versión con escala para ver la curva de Szegő

Este es el código Sage que genera los pngs que componen la animación con los factores de escala. La única diferencia con el código anterior (además de que los pngs se almacenan en una carpeta diferente), es que se grafican [(real(root)/i, imag(root)/i)] en lugar de [(real(root), imag(root))].

from sage.plot.colors import red, blue
f=0
n=50
folder="sagePngsScaled"
myPlot=Graphics()
for i in range(n+1):
    f=f+x^i/factorial(i)
    roots=f.solve(x,to_poly_solve=True)  # to_poly_solve makes Sage use Maxima's solver package to find ALL the roots
    numRoots=len(roots)
    myRoots= [roots[i].right() for i in range(numRoots)]
    filename=folder+"/"+"frame"+Integer(i).str().zfill(3)+".png"
    show("saved: "+ filename)
    p=list_plot(
        [(real(root)/i, imag(root)/i) for root in myRoots], 
        xmin=-Integer(1), 
        xmax=Integer(1), 
        ymin=-Integer(1), 
        ymax=Integer(1), 
        aspect_ratio=Integer(1), 
        color=blue)
    p.save(filename, dpi=200)

Más sobre la curva de Szegő

Se puede leer más sobre la curva de Szegő en estos lugares:

  1. Zemyan, S. M. (2005). On the Zeroes of the Nth Partial Sum of the Exponential Series. The American Mathematical Monthly, 112(10), 891–909. https://doi.org/10.2307/30037629

  2. (Ver la tabla de ceros y el gráfico en este artículo!) K.E. Iverson, los ceros de las sumas parciales de $e^z$. https://www.ams.org/journals/mcom/1953-07-043/S0025-5718-1953-0057013-0/S0025-5718-1953-0057013-0.pdf

  3. D.J Newman, T.J Rivlin, The zeros of the partial sums of the exponential function. https://doi.org/10.1016/0021-9045(72)90007-X

Otras imágenes interesantes

Con el código disponible, es fácil crear variaciones interesantes de la imagen original. Por ejemplo, esta es la gráfica con todos los ceros para $n=1$, $n=2$, …, $n=40$ al mismo tiempo, coloreados según el valor de $n$.

Este es el código que produce esa imagen:

from sage.plot.colors import red, blue
f=0
myPlot=Graphics()
n=40
for i in range(n+1):
    f=f+x^i/factorial(i)
    roots=f.solve(x,to_poly_solve=True)  # to_poly_solve makes Sage use Maxima's solver package to find ALL the roots
    numRoots=len(roots)
    myRoots= [roots[i].right() for i in range(numRoots)]
    show(i)
    myPlot+=list_plot(
        [(real(i), imag(i)) for i in myRoots],
        xmin=-Integer(20),
        xmax=Integer(20),
        aspect_ratio=Integer(1),
        color=red.blend(blue, fraction=i/10)
    )
show(myPlot)

Y acá está con colores de arcoíris (cada color corresponde a un valor de $n$).

Código en Sage:

from sage.plot.colors import red, blue
f=0
myPlot=Graphics()
n=40
myColors=rainbow(n)
for i in range(n+1):
    f=f+x^i/factorial(i)
    roots=f.solve(x,to_poly_solve=True)  # to_poly_solve makes Sage use Maxima's solver package to find ALL the roots
    numRoots=len(roots)
    myRoots= [roots[i].right() for i in range(numRoots)]
    show(i)
    myPlot+=list_plot(
        [(real(i), imag(i)) for i in myRoots], 
        xmin=-Integer(20), 
        xmax=Integer(20), 
        aspect_ratio=Integer(1), 
        color=Color(myColors[i]).darker(fraction=0.2)
    )
show(myPlot)

Suscríbase

¿Quiere recibir un email cuando haya una nueva entrada de blog? Suscríbase acá.