MN08: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Przykry (dyskusja | edycje)
mNie podano opisu zmian
 
Przykry (dyskusja | edycje)
mNie podano opisu zmian
Linia 21: Linia 21:
jednocześnie banalne i wydumane:
jednocześnie banalne i wydumane:


\beginprob
Dla danego zestawu <math>\displaystyle N</math> liczb <math>\displaystyle f_\alpha\in C</math>, <math>\displaystyle \alpha = 0,\ldots, N-1</math>,
Dla danego zestawu <math>\displaystyle N</math> liczb <math>\displaystyle f_\alpha\in C</math>, <math>\displaystyle \alpha = 0,\ldots, N-1</math>,
wyznaczyć  <math>\displaystyle N</math> wartości
wyznaczyć  <math>\displaystyle N</math> wartości
Linia 31: Linia 30:
pamiętamy, jednostka urojona <math>\displaystyle i</math> spełnia <math>\displaystyle i = \sqrt{-1}</math>. Taką operację nazywamy
pamiętamy, jednostka urojona <math>\displaystyle i</math> spełnia <math>\displaystyle i = \sqrt{-1}</math>. Taką operację nazywamy
''dyskretną transformacją Fouriera'', DFT.
''dyskretną transformacją Fouriera'', DFT.
\endprob


Ponieważ dane <math>\displaystyle f</math> są wektorem <math>\displaystyle f = [f_0,\ldots,f_{N-1}]^T</math>, wynik <math>\displaystyle c</math> też jest wektorem, a zadanie jest liniowe,
Ponieważ dane <math>\displaystyle f</math> są wektorem <math>\displaystyle f = [f_0,\ldots,f_{N-1}]^T</math>, wynik <math>\displaystyle c</math> też jest wektorem, a zadanie jest liniowe,
Linia 69: Linia 67:
Zauważmy, że nasza macierz ma jeszcze więcej specjalnej struktury, powtarza się
Zauważmy, że nasza macierz ma jeszcze więcej specjalnej struktury, powtarza się
w niej bardzo wiele takich samych współczynników (sprawdź dla <math>\displaystyle N=4</math>, w ogólności
w niej bardzo wiele takich samych współczynników (sprawdź dla <math>\displaystyle N=4</math>, w ogólności
ma tylko <math>\displaystyle N</math> różnych wyrazów), gdyż <math>\displaystyle \omega_N^N = 1</math> (<math>\displaystyle \omega^j</math> dla
ma tylko <math>\displaystyle N</math> różnych wyrazów), gdyż <math>\displaystyle \omega_N^N = 1</math> (dla
<math>\displaystyle j=0,\ldots,N-1</math> to nic innego jak wszystkie zespolone pierwiastki z jedynki), a
<math>\displaystyle j=0,\ldots,N-1</math>, <math>\displaystyle \omega_N^j</math>  to nic innego jak wszystkie zespolone pierwiastki z jedynki), a
jak wiadomo, mnożenie przez 1 nic nie kosztuje --- o ile tylko się wie, że ''gdzie'' jest ta jedynka. Z grubsza na tym właśnie będzie polegać siła algorytmu
jak wiadomo, mnożenie przez 1 nic nie kosztuje --- o ile tylko się wie, że ''gdzie'' jest ta jedynka. Z grubsza na tym właśnie będzie polegać siła algorytmu
FFT!
FFT!


W wyprowadzeniu algorytmu szybkiej transformacji Fouriera, (ang. Fast Fourier
W wyprowadzeniu algorytmu szybkiej transformacji Fouriera, ''Fast Fourier
Transform, FFT) oprzemy się poraz kolejny na regule "dziel i rządź". Dla
Transform, FFT ''oprzemy się poraz kolejny na regule "dziel i rządź". Dla
uproszczenia analizy przyjmiemy, że <math>\displaystyle N</math> jest naturalną potęgą dwójki, w
uproszczenia analizy przyjmiemy, że <math>\displaystyle N</math> jest naturalną potęgą dwójki, w
szczególności <math>\displaystyle N = 2m</math> dla pewnego naturalnego <math>\displaystyle m</math>.
szczególności <math>\displaystyle N = 2m</math> dla pewnego naturalnego <math>\displaystyle m</math>.
Linia 172: Linia 170:
interpolacji trygonometrycznej:  
interpolacji trygonometrycznej:  


\beginprob [Interpolacja trygonometryczna]
Dla danych węzłów <math>\displaystyle x_k = \frac{2\pi k }{N}</math>, <math>\displaystyle k = 0,\ldots,N-1</math>, znaleźć
Dla danych węzłów <math>\displaystyle x_k = \frac{2\pi k }{N}</math>, <math>\displaystyle k = 0,\ldots,N-1</math>, znaleźć
wielomian <math>\displaystyle P</math> (zmiennej rzeczywistej, o wartościach zespolonych) stopnia <math>\displaystyle \leq N-1</math> postaci
wielomian <math>\displaystyle P</math> (zmiennej rzeczywistej, o wartościach zespolonych) stopnia <math>\displaystyle \leq N-1</math> postaci
Linia 186: Linia 183:


dla zadanych wartości <math>\displaystyle y_k</math>.  
dla zadanych wartości <math>\displaystyle y_k</math>.  
\endprob


W języku macierzy DFT możemy zapisać zadanie interpolacji trygonometrycznej jako
W języku macierzy DFT możemy zapisać zadanie interpolacji trygonometrycznej jako
Linia 309: Linia 305:
for( i <nowiki>=</nowiki> 0; i < N; i++ )
for( i <nowiki>=</nowiki> 0; i < N; i++ )
{
{
printf("F[i, creal(F[i]), cimag(F[i]), i, creal(C[i]), cimag(C[i]));  
printf("F[\%d] <nowiki>=</nowiki> \%8.3lf + \%8.3lfi <nowiki>|</nowiki> C[\%d] <nowiki>=</nowiki> \%8.3lf + \%8.3lfi\n",
i, creal(F[i]), cimag(F[i]), i, creal(C[i]), cimag(C[i]));  
}
}


Linia 421: Linia 418:


{{lemat|||
{{lemat|||
  Niech <math>\displaystyle f\in W^r(a,b)</math> będzie funkcją  
   
Niech <math>\displaystyle f\in W^r(a,b)</math> będzie funkcją  
zerującą się w węzłach, tzn.  
zerującą się w węzłach, tzn.  


Linia 435: Linia 433:
}}
}}


\noindent
{{dowod|||
''Dowód''\quad Dla <math>\displaystyle r=1</math> funkcja <math>\displaystyle s'</math> jest przedziałami stała.  
Dla <math>\displaystyle r=1</math> funkcja <math>\displaystyle s'</math> jest przedziałami stała.  
Oznaczając przez <math>\displaystyle a_j</math> jej wartość na <math>\displaystyle [x_{j-1},x_j]</math> dostajemy  
Oznaczając przez <math>\displaystyle a_j</math> jej wartość na <math>\displaystyle [x_{j-1},x_j]</math> dostajemy  


Linia 473: Linia 471:
Funkcja <math>\displaystyle s^{(2r-1)}</math> jest przedziałami stała, a więc możemy  
Funkcja <math>\displaystyle s^{(2r-1)}</math> jest przedziałami stała, a więc możemy  
teraz zastosować ten sam argument jak dla <math>\displaystyle r=1</math>, aby pokazać,  
teraz zastosować ten sam argument jak dla <math>\displaystyle r=1</math>, aby pokazać,  
że ostatnia całka jest równa zeru. <math>\displaystyle \quad\Box</math>
że ostatnia całka jest równa zeru.}}


Funkcje sklejane chcielibyśmy zastosować do interpolacji funkcji.  
Funkcje sklejane chcielibyśmy zastosować do interpolacji funkcji.  
Linia 490: Linia 488:
}}
}}


\noindent
{{dowod|||
''Dowód''\quad Pokażemy najpierw, że jedyną naturalną  
Pokażemy najpierw, że jedyną naturalną  
funkcją sklejaną interpolującą dane zerowe jest funkcja zerowa.  
funkcją sklejaną interpolującą dane zerowe jest funkcja zerowa.  
Rzeczywiście, jeśli <math>\displaystyle s(x_j)=0</math> dla <math>\displaystyle 0\le j\le n</math>, to podstawiając  
Rzeczywiście, jeśli <math>\displaystyle s(x_j)=0</math> dla <math>\displaystyle 0\le j\le n</math>, to podstawiając  
w Lemacie [[##bwazny|Uzupelnic: bwazny ]] <math>\displaystyle f=s</math> otrzymujemy
w poprzednim Lemacie <math>\displaystyle f = s</math> otrzymujemy


<center><math>\displaystyle \int_a^b \Big(s^{(r)}(x)\Big)^2\,dx\,=\,0.
<center><math>\displaystyle \int_a^b \Big(s^{(r)}(x)\Big)^2\,dx\,=\,0.
Linia 547: Linia 545:
przy których, jak pokazaliśmy wcześniej, zerowa funkcja  
przy których, jak pokazaliśmy wcześniej, zerowa funkcja  
sklejana (której odpowiada <math>\displaystyle a_{i,j}=0</math>, <math>\displaystyle \forall i,j</math>)   
sklejana (której odpowiada <math>\displaystyle a_{i,j}=0</math>, <math>\displaystyle \forall i,j</math>)   
jest jedynym rozwiązaniem zadania interpolacyjnego.
jest jedynym rozwiązaniem zadania interpolacyjnego.}}
<math>\displaystyle \quad\Box</math>


Naturalne funkcje sklejane możemy więc używać do  
Naturalne funkcje sklejane możemy więc używać do  
Linia 567: Linia 564:
}}
}}


\noindent
{{dowod|||
''Dowód''\quad Jeśli przedstawimy <math>\displaystyle f</math> w postaci  
Jeśli przedstawimy <math>\displaystyle f</math> w postaci  
<math>\displaystyle f=s_f+(f-s_f)</math>, to  
<math>\displaystyle f=s_f+(f-s_f)</math>, to  


Linia 578: Linia 575:


Funkcja <math>\displaystyle f-s_f</math> jest w klasie <math>\displaystyle W^r(a,b)</math> i zeruje się w węzłach  
Funkcja <math>\displaystyle f-s_f</math> jest w klasie <math>\displaystyle W^r(a,b)</math> i zeruje się w węzłach  
<math>\displaystyle x_j</math>, <math>\displaystyle 0\le j\le n</math>. Z Lematu [[##bwazny|Uzupelnic: bwazny ]] wynika więc, że  
<math>\displaystyle x_j</math>, <math>\displaystyle 0\le j\le n</math>. Z Lematu wynika więc, że  
<math>\displaystyle \int_a^b s_f^{(r)}(x)(f-s_f)^{(r)}(x)dx=0</math>, a stąd ([[##nst|Uzupelnic: nst ]]).
<math>\displaystyle \int_a^b s_f^{(r)}(x)(f-s_f)^{(r)}(x)dx=0</math>, a stąd wynika teza.}}
<math>\displaystyle \quad\Box</math>


Wartość całki <math>\displaystyle \int_a^b(f^{(r)}(x))^2 dx</math> może być w  
Wartość całki <math>\displaystyle \int_a^b(f^{(r)}(x))^2 dx</math> może być w  
ogólności uważana za miarę gładkości funkcji.  
ogólności uważana za miarę gładkości funkcji.  
Nierówność ([[##nst|Uzupelnic: nst ]]) możemy więc zinterpretować w  
Dowiedzioną nierówność możemy więc zinterpretować w  
następujący sposób. Naturalna funkcja sklejana jest w  
następujący sposób. Naturalna funkcja sklejana jest w  
klasie <math>\displaystyle W^r(a,b)</math> najgładszą funkcją spełniającą dane  
klasie <math>\displaystyle W^r(a,b)</math> najgładszą funkcją spełniającą dane  
warunki interpolacyjne w wybranych węzłach <math>\displaystyle x_j</math>.  
warunki interpolacyjne w wybranych węzłach <math>\displaystyle x_j</math>.  
Konsekwencją Lematu [[##bwazny|Uzupelnic: bwazny ]] są również inne
aproksymacyjne własności naturalnych funkcji sklejanych,
zob. U. [[##optspln|Uzupelnic: optspln ]].


Jak już wspomnieliśmy, najczęściej używanymi są kubiczne  
Jak już wspomnieliśmy, najczęściej używanymi są kubiczne  
Linia 630: Linia 622:
Z warunków ciągłości dla <math>\displaystyle s_f'</math> dostajemy z kolei  
Z warunków ciągłości dla <math>\displaystyle s_f'</math> dostajemy z kolei  


<center><math>\displaystyle b_i+c_ih_i+d_ih_i^2//2\,=\,b_{i+1},  
<center><math>\displaystyle b_i+c_ih_i+d_ih_i^2/2\,=\,b_{i+1},  
     \qquad 0\le i\le n-2,
     \qquad 0\le i\le n-2,
</math></center>
</math></center>


i uwzględniając ([[##dei|Uzupelnic: dei ]])
oraz


<center><math>\displaystyle  
<center><math>\displaystyle  
   b_{i+1}\,=\,b_i+h_i(c_{i+1}+c_i)//2,  
   b_{i+1}\,=\,b_i+h_i(c_{i+1}+c_i)/2,  
     \qquad 0\le i\le n-2.  
     \qquad 0\le i\le n-2.  
</math></center>
</math></center>
Linia 644: Linia 636:


<center><math>\displaystyle  
<center><math>\displaystyle  
   a_i+b_ih_i+c_ih_i^2//2+d_ih_i^3//6\,=\,a_{i+1},  
   a_i+b_ih_i+c_ih_i^2/2+d_ih_i^3/6\,=\,a_{i+1},  
     \qquad 0\le i\le n-2.  
     \qquad 0\le i\le n-2.  
</math></center>
</math></center>


Równania ([[##dei|Uzupelnic: dei ]]),([[##bei|Uzupelnic: bei ]]) i ([[##aai|Uzupelnic: aai ]]) definiują  
Powyższe równania definiują  
nam na odcinku <math>\displaystyle [a,b]</math> naturalną kubiczną funkcję  
nam na odcinku <math>\displaystyle [a,b]</math> naturalną kubiczną funkcję  
sklejaną. Ponieważ poszukiwana funkcja sklejana <math>\displaystyle s_f</math> ma  
sklejaną. Ponieważ poszukiwana funkcja sklejana <math>\displaystyle s_f</math> ma  
interpolować <math>\displaystyle f</math>, mamy dotatkowych <math>\displaystyle n+1</math> warunków  
interpolować <math>\displaystyle f</math>, mamy dodatkowych <math>\displaystyle n+1</math> warunków  
interpolacyjnych <math>\displaystyle w_i(x_i)=f(x_i)</math>, <math>\displaystyle 0\le i\le n-1</math>,  
interpolacyjnych <math>\displaystyle w_i(x_i)=f(x_i)</math>, <math>\displaystyle 0\le i\le n-1</math>,  
oraz <math>\displaystyle w_{n-1}(x_n)=f(x_n)</math>, z których  
oraz <math>\displaystyle w_{n-1}(x_n)=f(x_n)</math>, z których  
Linia 659: Linia 651:
</math></center>
</math></center>


Teraz możemy ([[##aai|Uzupelnic: aai ]]) przepisać jako  
Teraz możemy warunki ciągłości przepisać jako  


<center><math>\displaystyle f(x_{i+1})\,=\,f(x_i)+b_ih_i+c_ih_i^2+d_ih_i^3//6,
<center><math>\displaystyle f(x_{i+1})\,=\,f(x_i)+b_ih_i+c_ih_i^2+d_ih_i^3/6,
</math></center>
</math></center>


Linia 669: Linia 661:


<center><math>\displaystyle  
<center><math>\displaystyle  
   b_i\,=\,f(x_i,x_{i+1})+h_i(c_{i+1}+2c_i)//6,  
   b_i\,=\,f(x_i,x_{i+1})+h_i(c_{i+1}+2c_i)/6,  
   \qquad 0\le i\le n-1,  
   \qquad 0\le i\le n-1,  
</math></center>
</math></center>
Linia 675: Linia 667:
gdzie <math>\displaystyle f(x_i,x_{i+1})</math> jest odpowiednią różnicą  
gdzie <math>\displaystyle f(x_i,x_{i+1})</math> jest odpowiednią różnicą  
dzieloną. Możemy teraz powyższe wyrażenie na <math>\displaystyle b_i</math>  
dzieloną. Możemy teraz powyższe wyrażenie na <math>\displaystyle b_i</math>  
podstawić w równaniach ([[##bei|Uzupelnic: bei ]]), aby otrzymać  
podstawić, aby otrzymać  


<center><math>\displaystyle c_ih_i//6+c_{i+1}(h_i+h_{i+1})//3+c_{i+1}h_{i+1}//6
<center><math>\displaystyle c_ih_i/6+c_{i+1}(h_i+h_{i+1})/3+c_{i+1}h_{i+1}/6
   \,=\,f(x_{i+1},x_{i+2})-f(x_i,x_{i+1}).  
   \,=\,f(x_{i+1},x_{i+2})-f(x_i,x_{i+1}).  
</math></center>
</math></center>
Linia 684: Linia 676:


<center><math>\displaystyle  
<center><math>\displaystyle  
   c_i^*\,=\,c_i//6,  
   c_i^*\,=\,c_i/6,  
</math></center>
</math></center>


Linia 721: Linia 713:


Ostatecznie, aby znaleźć współczynniki <math>\displaystyle a_i,b_i,c_i,d_i</math>  
Ostatecznie, aby znaleźć współczynniki <math>\displaystyle a_i,b_i,c_i,d_i</math>  
należy najpierw rozwiązać układ równań ([[##ukltrd|Uzupelnic: ukltrd ]]),  
należy najpierw rozwiązać układ równań liniowych,  
a potem zastosować wzory ([[##wzc|Uzupelnic: wzc ]]), ([[##dei|Uzupelnic: dei ]]),
a potem zastosować wzory definiujące pozostałe współczynniki.  
([[##wzb|Uzupelnic: wzb ]]) i ([[##wza|Uzupelnic: wza ]]).  


Zauważmy, że macierz układu ([[##ukltrd|Uzupelnic: ukltrd ]]) jest  
Zauważmy, że macierz układu równań liniowych jest  
trójdiagonalna i ma dominującą przekątną. Układ  
trójdiagonalna i ma dominującą przekątną. Układ  
można więc rozwiązać kosztem proporcjonalnym do  
można więc rozwiązać kosztem proporcjonalnym do  
wymiaru <math>\displaystyle n</math> używając algorytmu przeganiania z
wymiaru <math>\displaystyle n</math> używając algorytmu przeganiania. Koszt znalezienia wszystkich  
U. [[##trojd|Uzupelnic: trojd ]]. Koszt znalezienia wszystkich  
współczynników kubicznej funkcji sklejanej  
współczynników kubicznej funkcji sklejanej  
interpolującej <math>\displaystyle f</math> jest więc też proporcjonalny do <math>\displaystyle n</math>.  
interpolującej <math>\displaystyle f</math> jest więc też proporcjonalny do <math>\displaystyle n</math>.  
Linia 739: Linia 729:


{{twierdzenie|||
{{twierdzenie|||
Jeśli <math>\displaystyle f\in F^1_M([a,b])</math> to  
J
eśli <math>\displaystyle f\in F^1_M([a,b])</math> to  


<center><math>\displaystyle \|f-s_f\|_{C([a,b])}\,\le\,5\,M\,
<center><math>\displaystyle \|f-s_f\|_{C([a,b])}\,\le\,5\,M\,
Linia 765: Linia 756:


Z rozwinięcia <math>\displaystyle f</math> w szereg Taylora w punkcie <math>\displaystyle x_i</math> dostajemy  
Z rozwinięcia <math>\displaystyle f</math> w szereg Taylora w punkcie <math>\displaystyle x_i</math> dostajemy  
<math>\displaystyle f(x)=f(x_i)+f'(x_i)(x-x_i)+f''(\xi_1)(x-x_i)^2//2</math> oraz  
<math>\displaystyle f(x)=f(x_i)+f'(x_i)(x-x_i)+f''(\xi_1)(x-x_i)^2/2</math> oraz  
<math>\displaystyle (f(x_{i+1})-f(x_i))//h_i=f'(x_i)+h_if''(\xi_2)//2</math>. Stąd  
<math>\displaystyle (f(x_{i+1})-f(x_i))/h_i=f'(x_i)+h_if''(\xi_2)/2</math>. Stąd  


<center><math>\displaystyle \aligned \lefteqn{f(x)-s_f(x) \,=\, f(x)-w_i(x)} \\
<center><math>\displaystyle \aligned \lefteqn{f(x)-s_f(x) \,=\, f(x)-w_i(x)} \\

Wersja z 19:19, 29 sie 2006

Szybka transformacja Fouriera (FFT)

Algorytm FFT dla dyskretnej transformacji Fouriera (DFT) i jego krewniacy dla wyznaczania dyskretnej transformacji cosinusów (DCT i MDCT), choć dotyczą pozornie dość abstrakcyjnych zadań, zrewolucjonizowały wiele dziedzin życia. Między innymi, wykorzystuje się je w

  • kompresji obrazów w formacie JPEG (DCT)
  • kompresji dźwięku w formacie MP3 i pokrewnych (MDCT)
  • rozwiązywaniu ważnych równań różniczkowych cząstkowych (DFT)

a także do

  • fitrowania szumów (DFT)
  • szybkiego mnożenia wielomianów (DFT)

W niniejszym wykładzie ograniczymy się do przedstawienia szybkiego algorytmu rozwiązywania zadania DFT, algorytmy rozwiązywania zadań pokrewnych (DCT, MDCT, itp.) opierają się na podobnych zasadach.

Zacznijmy od postawienia zadania obliczeniowego DFT. Jest ono (pozornie!) jednocześnie banalne i wydumane:

Dla danego zestawu N liczb fαC, α=0,,N1, wyznaczyć N wartości

cj=α=0N1fαωNjα,

dla j=0,,N1, przy czym ωN=exp(i2ΠN). Jak pamiętamy, jednostka urojona i spełnia i=1. Taką operację nazywamy dyskretną transformacją Fouriera, DFT.

Ponieważ dane f są wektorem f=[f0,,fN1]T, wynik c też jest wektorem, a zadanie jest liniowe, możemy wszystko zapisać macierzowo:

c=FNf,

gdzie

FN=(ωNjα)j,α=0,,N1=(11111ωNωN2ωNN11ωN2ωN4ωN2(N1)1ωNN1ωN2(N1)ωN(N1)2).

Tak więc, gdyby naiwnie podejść do zadania, moglibyśmy je rozwiązać brutalnie, tworząc na początek macierz FN, a następnie wyznaczając iloczyn macierzy przez wektor, co łatwo zrobić kosztem O(N2) operacji. Dlatego istotne jest, że algorytm FFT, który za chwilę omówimy, będzie działać kosztem O(NlogN), czyli praktycznie liniowym (w obu przypadkach stałe proporcjonalności są równe 2) w dodatku będzie miał znacznie mniejsze wymagania pamięciowe. Już nawet gdy N=8 (przypadek kompresji JPEG), mamy N2=512, gdy tymczasem NlogN=24, więc zysk jest ponaddwudziestokrotny, co ma kapitalne znaczenie, bo zamiast czekać na zapis zdjęcia (powiedzmy) pół sekundy, czekalibyśmy długie 10 (sic!) sekund... albo nasza(?) cyfrówka kosztowałaby majątek...

Fakt

Macierz F jest symetryczna oraz 1NFN*FN=I.

Zauważmy, że nasza macierz ma jeszcze więcej specjalnej struktury, powtarza się w niej bardzo wiele takich samych współczynników (sprawdź dla N=4, w ogólności ma tylko N różnych wyrazów), gdyż ωNN=1 (dla j=0,,N1, ωNj to nic innego jak wszystkie zespolone pierwiastki z jedynki), a jak wiadomo, mnożenie przez 1 nic nie kosztuje --- o ile tylko się wie, że gdzie jest ta jedynka. Z grubsza na tym właśnie będzie polegać siła algorytmu FFT!

W wyprowadzeniu algorytmu szybkiej transformacji Fouriera, Fast Fourier Transform, FFT oprzemy się poraz kolejny na regule "dziel i rządź". Dla uproszczenia analizy przyjmiemy, że N jest naturalną potęgą dwójki, w szczególności N=2m dla pewnego naturalnego m.

Rzeczywiście, rozbijając naszą sumę na sumę po indeksach parzystych i sumę po indeksach nieparzystych, mamy

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned c_j &= f_0 \omega_N^{0\cdot j} + f_2 \omega_N^{2\cdot j} + \ldots + f_{N-2} \omega_N^{(N-2)\cdot j}\\ && + f_1 \omega_N^{1\cdot j} + f_3 \omega_N^{3\cdot j} + \ldots + f_{N-1} \omega_N^{(N-1)\cdot j}. \endaligned}

Suma po indeksach parzystych da się zapisać w postaci

k=0m1f2k(ωm)jk

i analogicznie suma po indeksach nieparzystych da się zapisać

ωNjk=0m1f2k+1(ωm)jk

gdyż ωN2=ωm, a więc wygląda na to, że nasze zadanie wyznaczenia dyskretnej transformacji Fouriera wymiaru N da się sprowadzić do analogicznych zadań mniejszego rozmiaru.

Rzeczywiście, korzystając z tego, że j=βm+j~, gdzie j~=0,,m1, oraz β=0 lub 1, mamy ωmj=ωmj~.

Oznaczając

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned \Phi_{\widetilde{j}} &= \sum_{k=0}^{m-1} f_{2k} \omega_m^{\widetilde{j}k}, \qquad \widetilde{j} = 0,\ldots, m-1,\\ \Psi_{\widetilde{j}} &= \sum_{k=0}^{m-1} f_{2k+1} \omega_m^{\widetilde{j}k}, \endaligned}

(jak widać są to DFT dla dwa razy krótszych wektorów, złożonych z tylko parzystych lub tylko nieparzystych współrzędnych f) dostajemy ostatecznie

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned c_{\widetilde{j}} = \Phi_{\widetilde{j}} + \omega_N^{\widetilde{j}} \Psi_{\widetilde{j}},\\ c_{\widetilde{j}+m} = \Phi_{\widetilde{j}} - \omega_N^{\widetilde{j}} \Psi_{\widetilde{j}}. \endaligned}

Tym samym, wyznaczenie DFT wymiaru N udało się rzeczywiście sprowadzić do wyznaczenia dwóch DFT wymiaru m=N/2 oraz drobnej manipulacji na ich wynikach zgodnie z powyższym wzorem. Oczywiście, te mniejsze transformacje można wyznaczyć takim samym sposobem, co prowadzi do zależności rekurencyjnej, która kończy się na wektorach długości 1, na których DFT to po prostu identyczność.

Proste sprawdzenie pokazuje, że koszt takiego algorytmu jest rzędu O(NlogN), a nie O(N2), jak dla naiwnego algorytmu mnożenia wektora przez gęstą macierz. Zysk jest więc, nawet dla niewielkich N, istotny.

Algorytm Prosta wersja algorytmu FFT



function y = fft(x)
	N = length(f);
	if N == 1 
		y = x;
	else
		<math>\displaystyle \omega</math> = <math>\displaystyle \exp(-\frac{2\Pi}{N}i)</math>;
		<math>\displaystyle \omega_k</math> = <math>\displaystyle \omega^{N/2-1}</math>;
		
		u = fft( f[0:2:N-2] );
		v = fft( f[1:2:N-1] );
		
		v = v * <math>\displaystyle \omega_k</math>;
		
		y = [ u+v ; u-v ];
	end
end

Efektywna implementacja FFT

Jak już zdążyliśmy się przyzwyczaić, w algorytmach numerycznych unikamy stosowania jawnej rekurencji, gdy tylko to możliwe. W przypadku FFT można jej również uniknąć, wyznaczając zawczasu --- korzystając z tzw. odwrócenia bitów --- porządek, w którym należy składać 1-wymiarowe DFT w coraz dłuższe wektory zgodnie ze wzorem powyżej tak, by na końcu dostać pożądany wektor c=FNf.

Ponadto, istnieją warianty algorytmu FFT, które np. działają na danych rzeczywistych. Na analogicznych zasadach co FFT oparte są również algorytmy wykonujące tzw. dyskretną transformację cosinusów (DCT) i jej wariant MDCT stosowany w kodekach audio takich jak MP3, AAC, czy Ogg-Vorbis..

Interpolacja trygonometryczna

Jednym z wielu zadań, w których daje się zastosować algorytm FFT, jest zadanie interpolacji trygonometrycznej:

Dla danych węzłów xk=2πkN, k=0,,N1, znaleźć wielomian P (zmiennej rzeczywistej, o wartościach zespolonych) stopnia N1 postaci

P(x)=k=0N1βkω¯k,

gdzie ω¯=eix=cos(x)+isin(x) (stąd nazwa: trygonometryczny) taki, że

P(xk)=yk,k=0,,N1,

dla zadanych wartości yk.

W języku macierzy DFT możemy zapisać zadanie interpolacji trygonometrycznej jako zadanie wyznaczania wektora β takiego, że

FN¯β=y

dla zadanego wektora y.

Twierdzenie

Współczynniki β=[β0,,βN1]T poszukiwanego wielomianu trygonometrycznego wyrażają się wzorem

β=1NFNy.

Dowód

Jak wiemy, 1NFN*FN=I, więc, z symetrii macierzy FN wynika, że (FN¯)1=1NFN.

Można pokazać, że gdy dane są rzeczywiste, zadanie interpolacji trygonometrycznej można wyrazić korzystając wyłącznie z liczb rzeczywistych. Jeśli ykR, k=0,,N1, to wtedy (rzeczywisty) wielomian trygonometryczny

p(x)=k=0N1(akcos(2kπNx)bksin(2kπNx)),

gdzie ak=Re(βk), bk=Im(βk), interpoluje yk w węzłach xk. Oczywiście, powyższa formuła w rzeczywistości ma o połowę mniej wyrazów, ze względu na własności funkcji trygonometrycznych.

Splot

W niektórych zastosowaniach potrzebne jest wyznaczenie splotu dwóch wektorów, to znaczy, wyznaczenie wyrażeń postaci

zk=j=0N1ujvkj,k=0,,N1.

Zapisując to macierzowo, szukamy iloczynu wektora u z cykliczną macierzą Toeplitza (macierz Toeplitza ma stałe wyrazy wzdłuż diagonali) wyznaczoną przez v,

z=(v0v1vN1vN1v0vN2v1vN1v0)(u0u1uN1),

tak więc pozornie zadanie wyznaczenia splotu powinno kosztować tyle, co mnożenie macierzy przez wektor, a więc O(N2) operacji. Tymczasem prosty rachunek pozwala sprawdzić, że odpowiednie transformacje Fouriera, z^=FNz, u^=FNu, v^=FNv spełniają równanie z macierzą diagonalną!

z^=N(v^0v^N1)u^=N(v^0u^0v^N1u^N1),

a to mnożenie daje się wykonać kosztem liniowym, tym samym całe zadanie daje się policzyć kosztem O(NlogN).

Biblioteki

Najpopularniejszą obecnie biblioteką implementującą algorytm FFT dla DFT, DCT i innych pokrewnych (bez ograniczenia, że wymiar jest naturalną potęgą dwójki), jest FFTW której nazwa jest skrótowcem od niezbyt skromnie brzmiącego ang. The Fastest Fourier Transform in the West. Z tej biblioteki korzystają m.in. funkcje MATLABa i Octave'a fft oraz ifft dla transformacji DFT (to znaczy mnożenia przez FN) i, odpowiednio, transformacji odwrotnej, 1NF¯N.

FFTW jest napisana w C i w dużym stopniu wykorzystuje możliwości współczesnych procesorów, takie jak potokowanie i instrukcje wektorowe SSE2 i SSE3. Poniżej pokazujemy przykładowy prościutki kod w C, realizujący DFT na pojedynczym wektorze zespolonym.

 
/* Kompilacja:
	gcc -o dft dft.c -lfftw3 -lm */
#include <complex.h> /* rozszerzenie GCC dające operacje na typach zespolonych */
#include <fftw3.h>
#include <math.h>
#define N 8

int main(void)
{
fftw_complex *F, *C;
fftw_plan Plan;
double normfactor = 1.0/N;
int i;

F = fftw_malloc( N * sizeof(fftw_complex) );
C = fftw_malloc( N * sizeof(fftw_complex) );

for( i = 0; i < N; i++ ) /* inicjalizacja wartości tablicy F */
{
	F[i] = i*M_PI*(1-0.5*I); 
}

Plan = fftw_plan_dft_1d( N, F, C, FFTW_FORWARD, FFTW_ESTIMATE );

fftw_execute( Plan );

for( i = 0; i < N; i++ ) /* normalizacja wyznaczonego C */
	C[i] *= normfactor; 

for( i = 0; i < N; i++ )
{
	printf("F[\%d] = \%8.3lf + \%8.3lfi | C[\%d] = \%8.3lf + \%8.3lfi\n", 
	i, creal(F[i]), cimag(F[i]), i, creal(C[i]), cimag(C[i])); 
}

/* .... teraz moglibyśmy zmienić wartości F i ponownie wyznaczyć C,
korzystając z tego samego Planu! */

/* sprzątamy */

fftw_destroy_plan( Plan );
fftw_free( F ); 
fftw_free( C ); 

return(0);
}

Zwrócmy uwagę na linię Plan=fftw_plan_dft_1d(...). To tutaj dokonywane są ustalenia, w jakiej kolejności mają być prowadzone obliczenia. Jest to operacja dość kosztowna, dlatego jeśli mamy wyznaczyć wiele takich samych DFT, tylko na różnych danych, należy przed pierwszą DFT taki plan zachować, a potem już gotowy wykorzystać, gdy chcemy aplikować DFT dla następnych danych.

Interpolacja splajnowa

Interpolacja wielomianami interpolacyjnymi, chociaż korzysta z funkcji gładkich i łatwo reprezentowalnych w komputerze, ma jednak również pewne wady. Zauważmy, że błąd interpolacji może być bardzo duży (zjawisko Rungego), a poza tym, interpolacja jest nielokalna: nawet mała zmiana warości funkcji w pojedynczym węźle może powodować dużą zmianę zachowania całego wielomianu interpolacyjnego. Czasem więc lepiej jest zastosować innego rodzaju interpolację, np. posługując się funkcjami sklejanymi.

Co to są funkcje sklejane?

W ogólności przez funkcję sklejaną rozumie się każdą funkcję przedziałami wielomianową. Nas będą jednak interesować szczególne funkcje tego typu i dlatego termin funkcje sklejane zarezerwujemy dla funkcji przedziałami wielomianowych i posiadających dodatkowe własności, które teraz określimy.

Niech dany będzie przedział skończony [a,b] i węzły

a=x0<x1<<xn=b,

przy czym n1.

Definicja

Funkcję Parser nie mógł rozpoznać (nieznana funkcja „\toR”): {\displaystyle \displaystyle s:R\toR} nazywamy funkcją sklejaną rzędu r (r1) odpowiadającą węzłom xj, 0jn, jeśli spełnione są następujące dwa warunki:

(i)
s jest wielomianem stopnia co najwyżej 2r1 na każdym

z przedziałów [xj1,xj], tzn. s|[xj1,xj]Π2r1, 1jn,

(ii)
s jest (2r2)-krotnie różniczkowalna w sposób

ciągły na całej prostej, tzn. sC(2r2)(R).

Jeśli ponadto

(iii)
s jest wielomianem stopnia co najwyżej r1 poza

(a,b), tzn. s|(,a],s|[b,+)Πr1,

to s jest naturalną funkcją sklejaną.

Klasę naturalnych funkcji sklejanych rzędu r opartych na węzłach xj będziemy oznaczać przez 𝒮r(x0,,xn), albo po prostu 𝒮r, jeśli węzły są ustalone.

Na przykład, funkcją sklejaną rzędu pierwszego (r=1) jest funkcja ciągła i liniowa na poszczególnych przedziałach [xj1,xj]. Jest ona naturalna, gdy poza (a,b) jest funkcją stała. Tego typu funkcje nazywamy liniowymi funkcjami sklejanymi.

Najważniejszymi a praktycznego punktu widzenia są jednak funkcje sklejane rzędu drugiego odpowiadające r=2. Są to funkcje, które są na R dwa razy różniczkowalne w sposób ciągły, a na każdym z podprzedziałów są wielomianami stopnia co najwyżej trzeciego. W tym przypadku mówimy o kubicznych funkcjach sklejanych. Funkcja sklejana kubiczna jest naturalna, gdy poza (a,b) jest wielomianem liniowym.

Interpolacja i gładkość

Pokażemy najpierw ważny lemat, który okaże się kluczem do dowodu dalszych twierdzeń.

Niech Wr(a,b) będzie klasą funkcji Parser nie mógł rozpoznać (nieznana funkcja „\toR”): {\displaystyle \displaystyle f:[a,b]\toR} takich, że f jest (r1) razy różniczkowalna na [a,b] w sposób ciągły oraz f(r)(x) istnieje prawie wszędzie na [a,b] i jest całkowalna z kwadratem, tzn.

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned W^r(a,b) &= \{\,f\in C^{(r-1)}([a,b]):\, f^{(r)}(x) \mbox{ istnieje p.w. na } [a,b] \\ && \qquad\qquad\qquad\qquad \mbox{ oraz } f^{(r)}\in{\cal L}_2(a,b)\,\}. \endaligned}

Oczywiście każda funkcja sklejana rzędu r (niekoniecznie naturalna) należy do Wr(a,b).

Lemat

Niech fWr(a,b) będzie funkcją zerującą się w węzłach, tzn.

f(xj)=0,0jn.

Wtedy dla dowolnej naturalnej funkcji sklejanej s𝒮r mamy

abf(r)(x)s(r)(x)dx=0.

Dowód

Dla r=1 funkcja s jest przedziałami stała. Oznaczając przez aj jej wartość na [xj1,xj] dostajemy

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned \int_a^b f'(x)s'(x)\,dx &= \sum_{j=1}^n\int_{t_{j-1}}^{t_j} f'(x)a_j\,dx \\ &= \sum_{j=1}^n a_j(f(x_j)-f(x_{j-1}))\,=\,0, \endaligned}

ponieważ f zeruje się w tj.

Rozpatrzmy teraz przypadek r2. Ponieważ

(f(r1)s(r))=f(r)s(r)+f(r1)s(r+1),

to

abf(r)(x)s(r)(x)dx=f(r1)(x)s(r)(x)|ababf(r1)(x)s(r+1)(x)dx.

Wobec tego, że s jest poza przedziałem (a,b) wielomianem stopnia co najwyżej r1 oraz s(r) jest ciągła na R, mamy s(r)(a)=0=s(r)(b), a stąd

f(r1)(x)s(r)(x)|ab=0.

Postępując podobnie, tzn. całkując przez części r1 razy otrzymujemy w końcu

abf(r)(x)s(r)(x)dx=(1)r1abf(x)s(2r1)(x)dx.

Funkcja s(2r1) jest przedziałami stała, a więc możemy teraz zastosować ten sam argument jak dla r=1, aby pokazać,

że ostatnia całka jest równa zeru.

Funkcje sklejane chcielibyśmy zastosować do interpolacji funkcji. Ważne jest więc, aby odpowiednie zadanie interpolacyjne miało jednoznaczne rozwiązanie.

Twierdzenie

Jeśli n+1r, to dla dowolnej funkcji Parser nie mógł rozpoznać (nieznana funkcja „\toR”): {\displaystyle \displaystyle f:[a,b]\toR} istnieje dokładnie jedna naturalna funkcja sklejana sf𝒮r interpolująca f w węzłach xj, tzn. taka, że

sf(xj)=f(xj),0jn.

Dowód

Pokażemy najpierw, że jedyną naturalną funkcją sklejaną interpolującą dane zerowe jest funkcja zerowa. Rzeczywiście, jeśli s(xj)=0 dla 0jn, to podstawiając w poprzednim Lemacie f=s otrzymujemy

ab(s(r)(x))2dx=0.

Stąd s(r) jest funkcją zerową, a więc s jest wielomianem stopnia co najwyżej r1 zerującym się w co najmniej n+1 punktach xj. Wobec tego, że n+1>r1, otrzymujemy s0.

Zauważmy teraz, że problem znalezienia naturalnej funkcji sklejanej s interpolującej f można sprowadzić do rozwiązania kwadratowego układu równań liniowych. Na każdym przedziale [xi1,xi], 1in, jest ona postaci

s(x)=wi(x)=j=02r1ai,jxj,

dla pewnych współczynników Parser nie mógł rozpoznać (nieznana funkcja „\inR”): {\displaystyle \displaystyle a_{i,j}\inR} , a na (,a] i [b,) mamy odpowiednio

s(x)=w0(x)=j=0r1a0,jxj

i

s(x)=wn+1(x)=j=0r1an+1,jxj.

Aby wyznaczyć s, musimy więc znaleźć ogółem 2r(n+1) współczynników ai,j, przy czym są one związane (2r1)(n+1) warunkami jednorodnymi wynikającymi z gładkości,

wi(k)(xi)=wi+1(k)(xi)

dla 0in i 0k2r2, oraz n+1 niejednorodnymi warunkami interpolacyjnymi,

wi(xi)=f(xi)

dla 0in. Otrzymujemy więc układ 2r(n+1) równań liniowych ze względu na 2r(n+1) niewiadomych ai,j.

Naturalna funkcja sklejana interpolująca f jest wyznaczona jednoznacznie wtedy i tylko wtedy, gdy układ ten ma jednoznaczne rozwiązanie. To zaś zachodzi, gdy zero jest jedynym rozwiązaniem układu jednorodnego. Rzeczywiście, układ jednorodny odpowiada zerowym warunkom interpolacyjnym, przy których, jak pokazaliśmy wcześniej, zerowa funkcja sklejana (której odpowiada ai,j=0, i,j)

jest jedynym rozwiązaniem zadania interpolacyjnego.

Naturalne funkcje sklejane możemy więc używać do interpolacji funkcji. Pokażemy teraz inną ich własność, która jest powodem dużego praktycznego zainteresowania funkcjami sklejanymi.

Twierdzenie

Niech fWr(a,b) i niech sf𝒮r będzie naturalną funkcją sklejaną rzędu r interpolującą f w węzłach xj, 0jn. Wtedy

ab(f(r)(x))2dxab(sf(r)(x))2dx.

Dowód

Jeśli przedstawimy f w postaci f=sf+(fsf), to

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned \int_a^b\Big(f^{(r)}(x)\Big)^2\,dx &= \int_a^b\Big(s_f^{(r)}(x)\Big)^2\,dx\,+\, \int_a^b\Big((f-s_f)^{(r)}(x)\Big)^2\,dx \\ & & \qquad\qquad 2\,\int_a^b s_f^{(r)}(x)(f-s_f)^{(r)}(x)\,dx. \endaligned}

Funkcja fsf jest w klasie Wr(a,b) i zeruje się w węzłach xj, 0jn. Z Lematu wynika więc, że

absf(r)(x)(fsf)(r)(x)dx=0, a stąd wynika teza.

Wartość całki ab(f(r)(x))2dx może być w ogólności uważana za miarę gładkości funkcji. Dowiedzioną nierówność możemy więc zinterpretować w następujący sposób. Naturalna funkcja sklejana jest w klasie Wr(a,b) najgładszą funkcją spełniającą dane warunki interpolacyjne w wybranych węzłach xj.

Jak już wspomnieliśmy, najczęściej używanymi są kubiczne funkcje sklejane. Dlatego rozpatrzymy je oddzielnie.

Kubiczne funkcje sklejane

Jeśli zdecydowaliśmy się na użycie kubicznych funkcji sklejanych to powstaje problem wyznaczenia sf𝒮2 interpolującej daną funkcję f, tzn. takiej, że sf(xi)=f(xi) dla 0in. W tym celu, na każdym przedziale [xi,xi+1] przedstawimy sf w postaci jej rozwinięcia w szereg Taylora w punkcie xi,

sf(x)=wi(x)=ai+bi(xxi)+ci(xxi)22+di(xxi)36,

i podamy algorytm obliczania ai,bi,ci,di dla 0in1.

Warunki brzegowe i warunki ciągłości dla sf dają nam w0(x0)=0=wn1(xn) oraz wi(xi+1)=wi+1(xi+1), czyli

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned c_0 &= 0, \\ c_i+d_ih_i &= c_{i+1}, \qquad 0\le i\le n-2, \\ c_{n-1}+d_{n-1}h_{n-1} &= 0, \endaligned}

gdzie hi=xi+1xi. Stąd, przyjmując dodatkowo cn=0, otrzymujemy

di=ci+1cihi,1in1.

Z warunków ciągłości dla sf dostajemy z kolei

bi+cihi+dihi2/2=bi+1,0in2,

oraz

bi+1=bi+hi(ci+1+ci)/2,0in2.

Warunki ciągłości sf dają w końcu

ai+bihi+cihi2/2+dihi3/6=ai+1,0in2.

Powyższe równania definiują nam na odcinku [a,b] naturalną kubiczną funkcję sklejaną. Ponieważ poszukiwana funkcja sklejana sf ma interpolować f, mamy dodatkowych n+1 warunków interpolacyjnych wi(xi)=f(xi), 0in1, oraz wn1(xn)=f(xn), z których

ai=f(xi),0in1.

Teraz możemy warunki ciągłości przepisać jako

f(xi+1)=f(xi)+bihi+cihi2+dihi3/6,

przy czym wzór ten zachodzi również dla i=n1. Po wyrugowaniu bi i podstawieniu di z (Uzupelnic: dei ), mamy

bi=f(xi,xi+1)+hi(ci+1+2ci)/6,0in1,

gdzie f(xi,xi+1) jest odpowiednią różnicą dzieloną. Możemy teraz powyższe wyrażenie na bi podstawić, aby otrzymać

cihi/6+ci+1(hi+hi+1)/3+ci+1hi+1/6=f(xi+1,xi+2)f(xi,xi+1).

Wprowadzając oznaczenie

ci*=ci/6,

możemy to równanie przepisać jako

hihi+hi+1ci*+2ci+1*+hi+1hi+hi+1ci+2*=f(xi,xi+1,xi+2),

0in2, albo w postaci macierzowej

(2w1u22w2u32w3un22wn2un12)(c1*c2*c3*cn2*cn1*)=(v1v2v3vn2vn1),

gdzie

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned && u_i\,=\,\frac{h_{i-1}}{h_{i-1}+h_i},\qquad w_i\,=\,\frac{h_i}{h_{i-1}+h_i}, \\ && v_i\,=\,f(x_{i-1},x_i,x_{i+1}). \endaligned}

Ostatecznie, aby znaleźć współczynniki ai,bi,ci,di należy najpierw rozwiązać układ równań liniowych, a potem zastosować wzory definiujące pozostałe współczynniki.

Zauważmy, że macierz układu równań liniowych jest trójdiagonalna i ma dominującą przekątną. Układ można więc rozwiązać kosztem proporcjonalnym do wymiaru n używając algorytmu przeganiania. Koszt znalezienia wszystkich współczynników kubicznej funkcji sklejanej interpolującej f jest więc też proporcjonalny do n.

Na końcu oszacujemy jeszcze błąd interpolacji naturalnymi kubicznymi funkcjami sklejanymi na przedziale [a,b]. Będziemy zakładać, że f jest dwa razy różniczkowalna w sposób ciągły.

Twierdzenie

J eśli fFM1([a,b]) to

fsfC([a,b])5Mmax1in(xixi1)2.

W szczególności, dla podziału równomiernego Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle x_i=a+(b-a)i/ń} , 0in, mamy

fsfC([a,b])5M(ban)2.

Dowód

Wykorzystamy obliczoną wcześniej postać interpolującej funkcji sklejanej sf. Dla x[xi,xi+1] mamy

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned w_i(x) &= f(x_i)\,+\,\left(\frac{f(x_{i+1})-f(x_i)}{h_i} -h_i(c_{i+1}^*+2c_i^*)\right)(x-x_i) \\ &&\qquad\qquad \,+\, 3c_i^*(x-x_i)^2\,+\,\frac{c_{i+1}^*-c_i^*}{h_i}(x-x_i)^3. \endaligned}

Z rozwinięcia f w szereg Taylora w punkcie xi dostajemy f(x)=f(xi)+f(xi)(xxi)+f(ξ1)(xxi)2/2 oraz (f(xi+1)f(xi))/hi=f(xi)+hif(ξ2)/2. Stąd

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned \lefteqn{f(x)-s_f(x) \,=\, f(x)-w_i(x)} \\ &= \frac{f''(\xi_1)}2(x-x_i)^2-\left(\frac{f''(\xi_2)}2 -(c_{i+1}^*+2c_i^*)\right)h_i(x-x_i) \\ & & \qquad\qquad\qquad -3c_i^*(x-x_i)^2 -\frac{c_{i+1}^*-c_i^*}{h_i}(x-x_i)^3, \endaligned}

oraz

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned |f(x)-s_f(x)| &\le &(M+2|c_{i+1}^*|+6|c_i^*|)h_i^2 \\ &= (M+8\max_{1\le i\le n-1}|c_i^*|)h_i^2. \endaligned}

Niech teraz max1in1|ci*|=|cs*|. Z postaci układu (Uzupelnic: ukltrd ) otrzymujemy

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned |c_s^*| &= 2|c_s^*|-|c_s^*|(u_s+w_s) \,\le\, |u_sc_{s-1}^*+2c_s^*+w_sc_{s+1}| \\ &= |f(x_{s-1},x_s,x_{s+1})|\,\le\, \Big|\frac{f''(\xi_3)}2\Big|\,\le\,\frac 12 M, \endaligned}

a stąd i z (Uzupelnic: psik )

|f(x)sf(x)|5Mhi2,

co kończy dowód.

Uwaga

Zamiast terminu funkcje sklejane używa się też często terminów splajny (ang. spline-sklejać), albo funkcje gięte.

Uwaga

Niech

WMr(a,b)={fWr(a,b):ab(f(r)(x))2dxM}.

Ustalmy węzły a=x0<<xn=b. Dla fWMr(a,b), niech sf będzie naturalną funkcją sklejaną interpolującą f w xj, 0jn, a af dowolną inną aproksymacją korzystającą jedynie z informacji o wartościach f w tych węzłach , tzn.

af=ϕ(f(x0),,f(xn)).

Załóżmy, że błąd aproksymacji mierzymy nie w normie Czebyszewa, ale w normie średniokwadratowej, zdefiniowanej jako

g2(a,b)=ab(g(x))2dx.

Wtedy

supfWMr(a,b)fsf2(a,b)supfWMr(a,b)faf2(a,b).

Aproksymacja naturalnymi funkcjami sklejanymi jest więc optymalna w klasie WMr(a,b).

Można również pokazać, że interpolacja sf* naturalnymi funkcjami sklejanymi na węzłach równoodległych Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle x_j=a+(b-a)j/ń} , 0jn, jest optymalna co do rzędu w klasie WMr(a,b), wśród wszystkich aproksymacji korzystających jedynie z informacji o wartościach funkcji w n+1 dowolnych punktach, oraz

maxfWMr(a,b)fsf*2(a,b)nr.
Uwaga

Tak jak wielomiany, naturalne funkcje sklejane interpolujące dane funkcje można reprezentować przez ich współczynniki w różnych bazach. Do tego celu można na przykład użyć bazy kanonicznej Kj, 0jn, zdefiniowanej równościami

Kj(xi)={0ij,1i=j,

przy której sf(x)=j=0nf(xj)Kj(x). Baza kanoniczna jest jednak niewygodna w użyciu, bo funkcje Kj w ogólności nie zerują się na żadnym podprzedziale, a tym samym manipulowanie nimi jest utrudnione.

Częściej używa się bazy B-sklejanej Bj, 0jn. W przypadku funkcji kubicznych, r=2, jest ona zdefiniowana przez następujące warunki:

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned B_j(x_j) &= 1, \qquad \mbox{ dla } 0\le j\le n, \\ B_j(x) &= 0,\qquad \mbox{ dla } x\le x_{j-2}, j\ge 2, \mbox{ oraz dla } x\ge x_{j+2}, j\le n-2. \endaligned}

Dla B0 i B1 dodatkowo żądamy, aby

B0(x0)=0=B1(x0),B1(x0)=0,

a dla Bn1 i Bn podobnie

Bn1(xn)=0=Bn(xn),Bn1(xn1)=0.

Wtedy Bj nie zeruje się tylko na przedziale (xj2,xj+2), Wyznaczenie współczynników rozwinięcia w bazie {Bi}i=0n funkcji sklejanej interpolującej f wymaga rozwiązania układu liniowego z macierzą trójdiagonalną {Bj(xi)}i,j=0n, a więc koszt obliczenia tych współczynników jest proporcjonalny do n.

Uwaga

Oprócz naturalnych funkcji sklejanych często rozpatruje się też okresowe funkcje sklejane. Są to funkcje Parser nie mógł rozpoznać (nieznana funkcja „\toR”): {\displaystyle \displaystyle \tilde s:R\toR} spełniające warunki (i), (ii) z Rozdziału Uzupelnic: warfs , oraz warunek:

(iii)'
s~(i) jest dla 0ir1

funkcją okresową o okresie (ba), tzn. s~(i)(x)=s~(i)(x+(ba)), x.

Klasę okresowych funkcji sklejanych rzędu r oznaczymy przez 𝒮~r. Funkcje te mają podobne własności jak naturalne funkcje sklejane. Dokładniej, niech

W~r(a,b)={fWr(a,b):f(i)(a)=f(i)(b),0ir1},

tzn. W~r(a,b) jest klasą funkcji z Wr(a,b), które można przedłużyć do funkcji, krórych wszystkie pochodne do rzędu r1 włącznie są (ba)-okresowe na R. Wtedy dla dowolnej funkcji fW~r(a,b) zerującej się w węzłach xj, oraz dla dowolnej s~𝒮~r mamy

abf(r)(x)s~(r)(x)dx=0.

Jest to odpowiednik Lematu Uzupelnic: bwazny w przypadku okresowym. W szczególności wynika z niego jednoznaczność rozwiązania zadania interpolacyjnego dla okresowych funkcji f (tzn. takich, że f(a)=f(b)), jak również odpowiednia własność minimalizacyjna okresowych funkcji sklejanych. Dokładniej, jeśli fW~r(a,b) oraz s~f𝒮~r interpoluje f w węzłach xj, 0jn, to

ab(f(r)(x))2dxab(s~f(r)(x))2dx.
Uwaga

Klasyczne zadanie aproksymacyjne w przestrzeniach funkcji definiuje się w następujący sposób.

Niech F będzie pewną przestrzenią liniową funkcji Parser nie mógł rozpoznać (nieznana funkcja „\toR”): {\displaystyle \displaystyle f:[a,b]\toR} , w której określona została norma . Niech VnF będzie podprzestrzenią w F wymiaru n. Dla danej fF, należy znaleźć funkcję vfF taką, że

fvf=minvVnfv.

Okazuje się, że tak postawione zadanie ma rozwiązanie vf, choć nie zawsze jest ono wyznaczone jednoznacznie, zob. ćw. Uzupelnic: rkl .

Jako przykład, rozpatrzmy F=Wr(a,b). Utożsamiając funkcje f1,f2Wr(a,b) takie, że f1(x)f2(x)Πr1, zdefiniujemy w Wr(a,b) normę

f=ab(f(r)(x))2dx.

Dla ustalonych węzłów a=x0<<xn=b, niech

Vn+1=𝒮r

będzie podprzestrzenią w Wr(a,b) naturalnych funkcji sklejanych rzędu r opartych węzłach xj, 0jn. Oczywiście dim𝒮r=n+1, co wynika z jednoznaczności rozwiązania w 𝒮r zadania interpolacji. Okazuje się, że wtedy optymalną dla fWr(a,b) jest naturalna funkcja sklejana sf interpolująca f w węzłach xj, tzn.

fsf=mins𝒮rfs.

Rzeczywiście, ponieważ norma w przestrzeni Wr(a,b) generowana jest przez iloczyn skalarny

(f1,f2)=abf1(r)(x)f2(r)(x)dx,

jest to przestrzeń unitarna. Znane twierdzenie mówi, że w przestrzeni unitarnej najbliższą danej f funkcją w dowolnej domkniętej podprzestrzeni V jest rzut prostopadły f na V, albo równoważnie, taka funkcja vfVn+1, że iloczyn skalarny

(fvf,v)=0,vV.

W naszym przypadku, ostatnia równość jest równoważna

ab(fvf)(r)(x)s(r)(x)dx=0,s𝒮r.

To zaś jest na mocy Lematu Uzupelnic: bwazny prawdą gdy vf interpoluje f w punktach xj, czyli vf=sf.

Dodajmy jeszcze, że nie zawsze interpolacja daje najlepszą aproksymację w sensie klasycznym, zob. ćw. Uzupelnic: intkla .