Zaawansowane algorytmy i struktury danych/Wykład 4: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Sank (dyskusja | edycje)
Sank (dyskusja | edycje)
Linia 134: Linia 134:


=== Odwrotna transformata Fouriera ===
=== Odwrotna transformata Fouriera ===
Aby zakończyć konstrukcję algorytmu dla szybkiego mnożenia
Aby zakończyć konstrukcję algorytmu dla szybkiego mnożenia
wielomianów pozostaje nam pokazanie jak wykonać obliczyć wielomian
wielomianów pozostaje nam pokazanie jak wykonać obliczyć wielomian
Linia 141: Linia 140:
w postaci macierzowej jako mnożenie macierzy przez wektor
w postaci macierzowej jako mnożenie macierzy przez wektor
<math>(A(x_0), A(x_1), \ldots, A(x_{n-1}))^T = V_n (a_0, a_1,
<math>(A(x_0), A(x_1), \ldots, A(x_{n-1}))^T = V_n (a_0, a_1,
\ldots, a_{n-1})^T</math>, gdzie <math>V(x_0,\ldots,x_{n-1})</math> jest macierzą
\ldots, a_{n-1})^T</math>, gdzie <math>V_n = V(x_0,\ldots,x_{n-1})</math> jest macierzą
Vandermonde'a zawierającą potęgi <math>x_i</math>
Vandermonde'a zawierającą potęgi <math>x_j</math>




Linia 183: Linia 182:


<center>
<center>
<math>V(x_0,\ldots,x_{n-1})_{i,j} = x_i^j</math>.
<math>(V_n)_{j,k} = V(x_0,\ldots,x_{n-1})_{j,k} = x_j^k</math>.
</center>
</center>


W celu wykonania operacji odwrotnej do SFT, czyli obliczenia wielomianu interpolacyjnego, musimy wykonać mnożenie
<math>V(x_0,\ldots,x_{n-1})^{-1} (A(x_0), A(x_1), \ldots, A(x_{n-1}))^T</math>.


Korzystając z definicji zbioru <math>X_n</math> otrzymujemy
Korzystając z definicji zbioru <math>X_n</math> otrzymujemy
Linia 194: Linia 190:


<center>
<center>
<math>V(x_0,\ldots,x_{n-1})_{i,j} = \left(e^{\frac{2\pi i}{n}}\right)^j
<math>V(x_0,\ldots,x_{n-1})_{j,k} = \left(e^{\frac{2\pi i j}{n}}\right)^k
= e^{\frac{2\pi ij}{n}}.</math>
= e^{\frac{2\pi ijk}{n}}.</math>
</center>
</center>


W celu wykonania operacji odwrotnej do SFT, czyli obliczenia wielomianu
interpolacyjnego, musimy wykonać mnożenie
<math>V_n^{-1} (A(x_0), A(x_1), \ldots, A(x_{n-1}))^T</math>.
{{lemat|||
Niech macierz <math>W_n</math> będzie zdefiniowana jako
<center><math>
\left(W_n\right)_{j,k} = \frac{1}{n} e^{\frac{-2\pi ijk}{n}},
</math></center>
jest macierzą odwrotną do macierzy <math>V_n</math>.
}
{{dowod|||
Pokażemy, że <math>V_n W_n = I</math>. Rozważmy pozycję <math>(j,k)</math>
macierzy <math>V_n W_n</math>:
<center><math>
\left(V_n W_n\right)_{j,k} = \sum_{l=0}^{n-1} \left(V_n\right)_{j,l} \left(W_n\right)_{l,k}
=\sum_{l=0}^{n-1} e^{\frac{2\pi i j l}{n}} \frac{1}{n} e^{\frac{-2\pi i l k}{n}} =
\sum_{l=0}^{n-1} \frac{1}{n} e^{\frac{2\pi l(j-k)}{n}} =
</math></center>
Jeżeli <math>j=k</math> to <math>e^{\frac{2\pi k(j-k)}{n}} =
1</math> i suma ta jest równa <math>1</math>. W przeciwnym przypadku
możemy skorzystać ze wzoru na sumę szeregu geometrycznego:
<center><math>
= \frac{1}{n} \frac{1 - e^{\frac{2\pi (n)(j-k)}{n}}}
{1 - e^{\frac{2\pi (j-k)}{n}} =
\frac{1}{n} \frac{1 - 1^{(j-k)}}
{1 - e^{\frac{2\pi (j-k)}{n}} = 0.
</math></center>
Czyli rzeczywiście <math>V_n W_n\right = I</math>. \qed
}}


{{lemat|||cos tam costam}}
Porównując postać macierzy <math>V_n</math> oraz macierzy <math>W_n</math>
{{dowod|||aaaa}}
widzimy, że w celu obliczenia transformaty odwrotnej możemy użyć
[[ZASD Moduł 4#algorytm_fft|Algorytmu Szybkiej Transformaty Fouriera]], musimy
tylko zamienić linijkę <math>\omega_m = e^{\frac{2\pi i}{n}}</math> na
<math>\omega_m = e^{-\frac{2\pi i}{n}}</math> i podzielić otrzymany wynik
przez <math>n</math>.

Wersja z 12:49, 19 lip 2006

Abstrakt

Naturalna metoda dodawania dwóch wielomianów wymaga czasu Θ(n), natomiast prosty algorytm mnożenia dwóch wielomianów stopnia n wymaga czasu Θ(n2). W wykładzie tym pokażemy, jak z wykorzystaniem szybkiej transformaty Fouriera (STF), wykonać wszystkie podstawowe operacje na wielomianach w czasie większym niż Θ(n) o czynnik polilogarytmiczny. Pokażemy jak dla wielomianów stopnia n:

  • mnożyć je w czasie O(nlogn),
  • obliczać wielomian interpolacyjny w czasie O(nlog2n),
  • obliczać wartość wielomianu w n punktach w czasie O(nlog2n),
  • dzielić wielomiany w czasie O(nlog3n).

Mnożenie wielomianów w punktach

Niech A(x)=i=0n1aixi i B(x)=i=0n1bixi będzą wielomianami stopnia n nad ciałem F. Wielomiany te możemy jednoznaczne reprezentować poprzez ich wartości w n punktach. Następujące twierdzenie zostało sformułowane w ramach wykładu z Metod Numerycznych.

Twierdzenie [Twierdzenie o interpolacji wielomianów]

Dla dowolnego zbioru n par X={(x0,y0),(x1,y1),,(xn1,yn1)} takiego, że wszystkie wartości xi są parami różne, istnieje jedyny wielomian C(x) stopnia n taki, że C(xi)=yi dla i=0,1,,n1.


Niech X będzie ustalonym zbiorem parami różnych punktów x0,,x2n1F. Dla tego zbioru punktów możemy wyznaczyć zbiory wartości wielomianów:


XA={(x0,A(x0)),(x1,A(x1),,(x2n1,A(x2n1))}

XB={(x0,B(x0)),(x1,B(x1),,(x2n1,B(x2n1))}


Niech C będzie wynikiem mnożenia wielomianów A i B, mamy wtedy


C(xi)=A(xi)B(xi).


Ponieważ stopień wielomianu C jest nie większy niż 2n to z Twierdzenia o interpolacji zbiór wartości


XA×B={(x0,A(x0)B(x0)),(x1,A(x1)B(x1),,(2xn1,A(x2n1)B(x2n1))},


jednoznacznie wyznacza wielomian A×B. Mając zbiory XA i XB możemy wyznaczyć zbiór XC w czasie O(n). Procedura ta jest przedstawiona na następującym rysunku:


<flash>file=Zasd_fft1.swf|width=460|height=350</flash>


Jednak aby ostatecznie otrzymać szybszy algorytm niż algorytm naiwny musimy pokazać jak rozwiązać problem obliczania wartości wielomianu w n punktach w czasie szybszym niż Θ(n2). Podobnie musimy umieć obliczać wielomian interpolacyjny dla danego zbioru punktów.

Szybka transformata Fouriera (STF)

Problem obliczania wartości wielomianu w n punktach i problem jego interpolacji rozwiążemy wykorzystując szybką transformatę Fouriera. W poprzednim rozdziale nie zakładaliśmy nic na temat zbioru punktów X. Głównym pomysłem w konstrukcji algorytmu STF będzie właśnie wybór odpowiedniego zbioru punktów X tak, aby jak największa ilość wykonywanych obliczeń powtarzała się.

Założymy chcemy obliczyć wartości wielomianu A(x)=i=0n1aixi oraz n jest parzyste. Jeżeli n jest nieparzyste to dodajemy na początek A(x) jednomian 0xn+1 co nie zmienia nam wyniku działania algorytmu. Punkty Xn={x0,x1,,xn1} zdefiniujemy w następujący sposób:


xi=e2πin.


Dla wielomianu A(x) definiujemy dwa nowe wielomiany A[0](x) i A[1](x) poprzez wybranie do nich współczynników A(x) o numerach odpowiednio parzystych i nieparzystych:


A[0](x)=a0+a2x+a4x2++an2xn21,

A[1](x)=a1+a3x+a5x2++an1xn21.


Wielomiany A[0](x) oraz A[1](x) są stopnia co najwyżej n2. Co więcej zachodzi:

A(x)=A[0](x2)+xA[1](x2)      (1)

Widzimy teraz, że problem ewaluacji wielomianu A(x) w punktach ωn0,ωn1,,ωnn1 sprowadza się do:

  • ewaluacji wielomianów A[0](x) i A[1](x)

w punktach


X={x02,x12,,xn12}.


  • a następnie obliczenie wartości A(x)wyniku zgodnie ze wzorem (1).

Zauważmy, że z definicji punktów $x_i$ mamy:


xi2=(e2πin)2=e2πin/2.


Możemy teraz zauważyć, że zachodzi xi2=xi+n22, a więc X=Xn2. Udało nam się więc zredukować problem rozmiaru n - obliczenia wartości wielomianu A(x) stopnia n w ndo punktach, do dwóch problemów rozmiaru n2 - obliczenia wartości wielomianów A[0](x) i A[1](x) stopnia n2 w n2 punktach. Możemy teraz zastosować tą technikę rekurencyjne otrzymując następujący algorytm.

Równanie rekurencyjne na czas działania procedury STF wygląda następująco:


T(n)=2T(n2)+Θ(n)=Θ(nlogn).


Odwrotna transformata Fouriera

Aby zakończyć konstrukcję algorytmu dla szybkiego mnożenia wielomianów pozostaje nam pokazanie jak wykonać obliczyć wielomian interpolujący dla zbioru punktów Xn. Obliczenie wykonane w czasie szybkiej transformaty Fouriera możemy przedstawić w postaci macierzowej jako mnożenie macierzy przez wektor (A(x0),A(x1),,A(xn1))T=Vn(a0,a1,,an1)T, gdzie Vn=V(x0,,xn1) jest macierzą Vandermonde'a zawierającą potęgi xj


(A(x0)A(x1)A(x2)A(xn1))=[x00x01x02x03x0n1x10x11x12x13x1n1x20x21x22x23x2n1xn10xn11xn12xn13xn1n1](a0a1a2an1)


Element macierzy V(x0,,xn1) dany jest jako


(Vn)j,k=V(x0,,xn1)j,k=xjk.


Korzystając z definicji zbioru Xn otrzymujemy


V(x0,,xn1)j,k=(e2πijn)k=e2πijkn.

W celu wykonania operacji odwrotnej do SFT, czyli obliczenia wielomianu interpolacyjnego, musimy wykonać mnożenie Vn1(A(x0),A(x1),,A(xn1))T.

{{lemat||| Niech macierz Wn będzie zdefiniowana jako


(Wn)j,k=1ne2πijkn,


jest macierzą odwrotną do macierzy Vn. } Dowód

Pokażemy, że VnWn=I. Rozważmy pozycję (j,k) macierzy VnWn:


(VnWn)j,k=l=0n1(Vn)j,l(Wn)l,k=l=0n1e2πijln1ne2πilkn=l=0n11ne2πl(jk)n=


Jeżeli j=k to e2πk(jk)n=1 i suma ta jest równa 1. W przeciwnym przypadku możemy skorzystać ze wzoru na sumę szeregu geometrycznego:


Parser nie mógł rozpoznać (błąd składni): {\displaystyle = \frac{1}{n} \frac{1 - e^{\frac{2\pi (n)(j-k)}{n}}} {1 - e^{\frac{2\pi (j-k)}{n}} = \frac{1}{n} \frac{1 - 1^{(j-k)}} {1 - e^{\frac{2\pi (j-k)}{n}} = 0. }


Czyli rzeczywiście Parser nie mógł rozpoznać (błąd składni): {\displaystyle V_n W_n\right = I} . \qed

Porównując postać macierzy Vn oraz macierzy Wn widzimy, że w celu obliczenia transformaty odwrotnej możemy użyć Algorytmu Szybkiej Transformaty Fouriera, musimy tylko zamienić linijkę ωm=e2πin na ωm=e2πin i podzielić otrzymany wynik przez n.