Grupo4 - FFT: mudanças entre as edições
Sem resumo de edição |
Sem resumo de edição |
||
Linha 124: | Linha 124: | ||
<math> >>>~~~~ return ~ \vec{A};</math> | <math> >>>~~~~ return ~ \vec{A};</math> | ||
== Implementação == | |||
A natureza recursiva do algoritmo da transformada rápida de fourier o torna ideal para implementações em linguagens funcionais como Haskell. Abaixo exibimos as partes mais relevantes do código, onde omitimos inclusões de bibliotecas e a definição das funções auxiliares evens e odds. | |||
<source lang="haskell" line='line'> | |||
--esse termo multiplica o somatório de termos ímpares | |||
f xs n = exp $ -(0:+2*pi)*n / genericLength xs | |||
--caso a função seja chamada com apenas dois termos, temos o caso base | |||
ffti [x,y] n = x + y * (exp $ -(0:+pi)*n) | |||
--caso contrário aplique a função recursivamente separando o somatório em | |||
-- termos com índice par e com índice ímpar | |||
ffti xs n = ffti (evens xs) n + f xs n * ffti (odds xs) n | |||
--função que calcula os n coeficientes (ffti calcula um coeficiente) | |||
fft xs [] = [] | |||
fft xs (y:ys) = (ffti xs y):(fft xs ys) | |||
--exemplo | |||
fft [0, 1, 4, 9] [0,1,2,3] | |||
--saída ( :+ indica número complexo em Haskell) | |||
[14.0 :+ 0.0, -4.0 :+ 8.0, -6.0 :+ 0.0, -4.0 :+ -8.0)] | |||
</source> | |||
Embora não seja uma linguagem puramente funcional Wolfram Mathematica também se presta a uma implementação direta e clara. | |||
<source lang="css" line='line'> | |||
// caso base de uma lista contendo apenas dois termos | |||
fft[{x_, y_}, n_] := x + y Exp[-I Pi n ] | |||
// caso contrário, divida a lista entre termos com índice ímpar e par | |||
// e aplique a função recursivamente | |||
fft[f_List, n_] := fft[Downsample[f, 2, 1], n] + | |||
Exp[-((I 2 Pi n )/Length[f])] fft[Downsample[f, 2, 2], n] | |||
//acima calcula-se com um coeficiente abaixo calcula-se todos | |||
fft[f_List] := Table[fft[f, n] // N, {n, 0, Length[f] - 1}] | |||
//exemplo | |||
fft[{0, 1, 4, 9}] | |||
{14., -4. + 8. I, -6., -4. - 8. I} | |||
</source> | |||
== Exemplos == | |||
Alguns exemplos básicos da transformada de fourier utilizando o código acima: | |||
=== Gaussiana === | |||
[[Arquivo:gaussian1.png]] | |||
[[Arquivo:gaussian2.png]] | |||
[[Arquivo:gaussian3.png]] | |||
[[Arquivo:osch.jpg]] | |||
[[Arquivo:oschim.png]] | |||
[[Arquivo:oschre.png]] |
Edição das 16h17min de 29 de outubro de 2017
A Transformada rápida de Fourier (em inglês Fast Fourier Transform, ou FFT) é um algoritmo que torna viável o cálculo da Transformada Discreta de Fourier (DFT), que é a forma discretizada da [Transformada de Fourier]. A FFT permite transformar de forma rápida uma série de sinais discretos em uma amostra contendo as frequências desses sinais, desde que satisfaça algumas propriedades.
Transformada Discreta de Fourier
Em muitas aplicações se tem informação sobre um conjunto de dados, ao invés de uma função contínua. A Transformada Discreta de Fourier transforma esse conjunto de dados em um conjunto de tamanho igual com informação sobre as frequências da função que satisfaz o conjunto de dados.
Para um conjunto de dados igualmente espaçados, pode-se, ao considerar os dados como um período de uma função periódica, cujo período normalmente é considerado entre para facilitar o cálculo (e que pode sempre ser transformada em uma função nesse interválo), mostrar que a transformada discreta de Fourier pode ser dada pela equação:
A sua inversa é, em paralelo ao caso da transformada contínua,
A transformada também pode ser expressa em forma vetorial, como
onde é definido como
O cálculo dessa expressão leva em torno de passos para o resultado. Uma amostra com 3,000 pontos precisa de 9,000,000 operações para a transformada ser obtida, tornando a DFT inviável para aplicações rápidas.
Transformada Rápida de Fourier
É possível calcular a transformada com passos. Para isso se dispõe de um algoritmo chamado Transformada Rápida de Fourier. Considera-se um conjunto de pontos (com inteiro, então, da definição da DFT
podemos dividir o somatório em 2:
onde a soma em vermelho é a parte par e a soma em azul é a parte ímpar da transformada. As duas somas tem o mesmo expoente, que agora é dividido por . Desse expoente, é evidente a relação entre o ponto e o ponto
Com essa relação, podemos ver que e tem o mesmo expoente e podem ser calculadas ao mesmo tempo. Mais que isso, a nova forma da transformada pode ser sucessivamente dividida, cada vez produzindo somas com limites menores.
Exemplo
Suponha que temos a função sinusoidal e fazemos quatro medidas no intervalo de 1 segundo, resultando em
Com essas 4 medidas, podemos dividir a soma 2 vezes:
e como temos podemos calcular
FFT para N diferente de uma potência de 2
Mesmo com a FFT sendo um algoritmo extremamente eficiente para , esse dificilmente é o caso que encotramos. Ainda assim, para altamente composto () o algoritmo ainda resulta em uma boa queda no tempo de cálculo.
Para o caso mais simples a transformada pode ser escrita como
onde
assim a transformada que antes necessitava de N calculos, agora pode ser vista como calculos.
Algorítmo (usando recursão)
Implementação
A natureza recursiva do algoritmo da transformada rápida de fourier o torna ideal para implementações em linguagens funcionais como Haskell. Abaixo exibimos as partes mais relevantes do código, onde omitimos inclusões de bibliotecas e a definição das funções auxiliares evens e odds.
--esse termo multiplica o somatório de termos ímpares
f xs n = exp $ -(0:+2*pi)*n / genericLength xs
--caso a função seja chamada com apenas dois termos, temos o caso base
ffti [x,y] n = x + y * (exp $ -(0:+pi)*n)
--caso contrário aplique a função recursivamente separando o somatório em
-- termos com índice par e com índice ímpar
ffti xs n = ffti (evens xs) n + f xs n * ffti (odds xs) n
--função que calcula os n coeficientes (ffti calcula um coeficiente)
fft xs [] = []
fft xs (y:ys) = (ffti xs y):(fft xs ys)
--exemplo
fft [0, 1, 4, 9] [0,1,2,3]
--saída ( :+ indica número complexo em Haskell)
[14.0 :+ 0.0, -4.0 :+ 8.0, -6.0 :+ 0.0, -4.0 :+ -8.0)]
Embora não seja uma linguagem puramente funcional Wolfram Mathematica também se presta a uma implementação direta e clara.
// caso base de uma lista contendo apenas dois termos
fft[{x_, y_}, n_] := x + y Exp[-I Pi n ]
// caso contrário, divida a lista entre termos com índice ímpar e par
// e aplique a função recursivamente
fft[f_List, n_] := fft[Downsample[f, 2, 1], n] +
Exp[-((I 2 Pi n )/Length[f])] fft[Downsample[f, 2, 2], n]
//acima calcula-se com um coeficiente abaixo calcula-se todos
fft[f_List] := Table[fft[f, n] // N, {n, 0, Length[f] - 1}]
//exemplo
fft[{0, 1, 4, 9}]
{14., -4. + 8. I, -6., -4. - 8. I}
Exemplos
Alguns exemplos básicos da transformada de fourier utilizando o código acima: