Creo que todos los elementos teóricos están presentes en las respuestas de los demás, pero no la razón pragmática por la que la FFT reduce la complejidad en un factor significativo (y de ahí la popularidad de este algoritmo, entre otras cosas).
Aplicar la DFT equivale a multiplicar una matriz por un vector (la señal original muestreada, por ejemplo, en la que cada entrada del vector es una muestra). Esa matriz es la matriz de Fourier. Digamos que tenemos $2n$ muestras, la matriz a considerar es entonces (hasta un factor constante)
$(F_{2n})_{jk} = \exp(i\pi \times jk/n)$
donde $i=\sqrt{-1}$ . Estas son las raíces de la unidad.
Ahora la magia se produce gracias a un mariposa de estas matrices, puedes descomponerlas en un producto de matrices: cada una de las cuales es barata de aplicar a un vector (cf. a continuación)
Por ejemplo $F_4$ viene dada (hasta un factor) por:
$$ F_4 \propto \left(\begin{array}{cccc} 1 & 1 & 1 & 1\\ 1 & i & i^2 & i^3 \\ 1 & i^2 & i^4 & i^6 \\ 1 & i^3 & i^6 & i^9 \end{array} \right) \propto \left(\begin{array}{cc|cc} 1 & 0 & 1 & 0\\ 0 & 1 & 0 & i\\\hline 1 & 0 & -1 & 0\\ 0 & 1 & 0 & -i \end{array} \right) \left(\begin{array}{cc|cc} 1 & 1 & 0 & 0\\ 1 & i^2 & 0 & 0\\\hline 0 & 0 & 1 & 1\\ 0 & 0 & 1 & i^2 \end{array} \right) \left(\begin{array}{cccc} 1 & 0 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1 \end{array} \right) $$
Veamos las dos primeras matrices: su estructura es muy típica, (se podría demostrar mediante recursividad cómo se generaliza esto) pero hablaremos de esto más adelante. Lo que nos importa ahora es que hay sólo 2 entradas distintas de cero por línea . Esto significa que al considerar la aplicación de una de esas matrices a un vector, el número de operaciones a realizar es una modesta constante de veces $n$ . Por otra parte, el número de matrices en la descomposición crece como $\log n$ . Así que en general la complejidad se escala como $n\times \log n$ donde un producto matricial-vectorial básico no estructurado se escalaría como $n^2$ .
(Para aclarar este punto: empezando por la derecha, se aplica una matriz a un vector, esto cuesta $O(n)$ entonces se aplica una matriz al vector resultante, de nuevo $O(n)$ ya que hay $O(\log n)$ matrices, la complejidad global es $O(n\log n)$ donde $O$ significa (aproximadamente) "del orden de", para más información sobre la notación big-O, consulte la página de la wikipedia (1))
Finalmente, la última matriz de la descomposición es a inversión de bits matriz. Sin entrar en detalles, puede calcularse de forma extremadamente eficiente. (Pero incluso ingenuamente, el coste no es obviamente más que lineal en $n$ ).
Siempre que no te haya perdido aquí, vamos a generalizar un poco: la matriz $F_{2n}$ tiene la siguiente forma (no es difícil de comprobar)
$$ F_{2n} \propto \left(\begin{array}{cc} I_n & A_n \\ I_n & -A_n \end{array}\right) \left(\begin{array}{cc} F_n & 0 \\ 0 & F_n \end{array}\right) B_{2n} $$
donde $B_{2n}$ es una matriz de inversión de bits de dimensiones adecuadas, $F_n$ es la matriz DFT de orden $n$ y, por tanto, esta matriz puede expresarse como un producto, etc. $I_n$ es la matriz de identidad de tamaño $n\times n$ y $A_n$ es una matriz diagonal con las potencias de $i$ de $0$ a $n-1$ .
Por cierto, ahora puedes observar que es deseable que el tamaño de tu vector-muestra original sea una potencia de $2$ . Si no es el caso, es más barato para rellenar su vector con ceros (esto se llama en realidad relleno cero )
Lo último que hay que aclarar es el mariposa (véase también [2]). Para ello, nada mejor que un pequeño dibujo (siento no haber querido hacer esto en Tikz, si hay algún héroe por ahí...). Si representas los vectores después de cada etapa por puntos y conectas los puntos del vector original al vector después de aplicar la matriz, obtienes este bonito diagrama (ignorando la inversión de bits)
He intentado dejar claro en el diagrama que el primer nivel corresponde a 4 aplicaciones de $F_2$ , el siguiente nivel a 2 aplicaciones de $F_4$ etc. Para que quede más claro, empezando por la derecha significa que la primera multiplicación matricial después de la inversión de bits será
- para la primera entrada, hay que mirar la primera y la segunda entrada del vector original (correspondientes a entradas distintas de cero en las posiciones (1,1) y (1,2) de la matriz de ese nivel)
- para la siguiente entrada, hay que mirar la primera y la segunda entrada (esto hace que el primer bloque de la columna "F2" (correspondiente a las entradas distintas de cero en las posiciones (2,1) y (2,2))
etc. Además, obsérvese que, en cada nivel, podemos considerar bloques de entradas independientemente. De nuevo, esto conduce a una mayor optimización que puede hacer que la FFT sea muy muy eficiente.
Ps: He ignorado todas las constantes de multiplicación ya que es un cálculo O(1), es fácil comprobar cuales son y dependerá de las convenciones que estés usando.
- https://en.wikipedia.org/wiki/Big_O_notation
- https://en.wikipedia.org/wiki/Butterfly_diagram
ver también: https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm#Pseudocode
donde hay disponible un pseudocódigo que ilustra cómo se codificaría la FFT recursivamente.
Otro buen recurso para ver cómo codificar la FFT desde cero: https://jakevdp.github.io/blog/2013/08/28/understanding-the-fft/
3 votos
También aclararía mucho más esta pregunta si explicara lo que entiende por transformada de Fourier ordinaria. Entonces los demás usuarios sabrían qué términos utilizar para explicarte la FFT.
7 votos
Mucha gente puede explicarlo en términos sencillos, pero hay que dar un punto de partida. Así las cosas no está claro lo que pregunta ? Recuerde que pedir una visita guiada a un capítulo de un libro se cerrará como demasiado amplio .
1 votos
Está bien explicado en Algoritmos de Dasgupta, Papadimitriou y Vazirani .
1 votos
El otro día encontré este vídeo, quizá ayude a intuir un poco más: youtube.com/watch?v=FjmwwDHT98c
1 votos
Aquí di una explicación rápida (un párrafo) pero sorprendentemente completa de la transformada discreta de Fourier: math.stackexchange.com/a/582626/40119 . La transformada discreta de Fourier simplemente cambia de base a una base especial, la "base discreta de Fourier", que es una base de vectores propios para el operador de desplazamiento cíclico $S$ en $\mathbb C^n$ . Puedes calcular fácilmente estos vectores propios ahora mismo. Porque cualquier operador lineal invariante por desplazamiento conmuta con $S$ un teorema de diagonalización simultánea nos dice que cualquier operador invariante por desplazamiento está diagonalizado por la base discreta de Fourier.
0 votos
La DFT es un operador lineal ortonormal/unitario (matriz) que transforma una señal en una suma de senos (complejos). eso es todo lo que hay que entender. la serie de Fourier es un operador ortonormal/unitario que transforma una ( $L^2$ ) en una señal ( $l^2$ ) de senos (complejos). la transformada de Fourier es un operador unitario que transforma a $L^2$ a una función $L^2$ integral de los senos (complejos). La ortonormalidad de todas estas transformaciones (lineales) garantiza que las transformaciones inversas son prácticamente iguales.