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)
Nie podano opisu zmian
Linia 149: Linia 149:
te wyniki w celu wyliczenia SFT dla wielomianu <math>A(x)</math>.
te wyniki w celu wyliczenia SFT dla wielomianu <math>A(x)</math>.
Przeanalizujmy teraz wykonanie pętli. Zauważmy najpierw, że w
Przeanalizujmy teraz wykonanie pętli. Zauważmy najpierw, że w
<math>k</math>'tym  kroku pętli mamy <math>\omega = \omega_n^k  
<math>k</math>'tym  kroku pętli mamy <math>\omega = \omega_n^k
= e^{\frac{2\pi i k}{n}} = x_k.</math>. Czyli:
= e^{\frac{2\pi i k}{n}} = x_k.</math>. Czyli:


Linia 169: Linia 169:


<center><math>
<center><math>
y_{k+\frac{n}{2}} = y_k^{[0]} - x_k y_k^{[1]}  
y_{k+\frac{n}{2}} = y_k^{[0]} - x_k y_k^{[1]}
= A^{[0]}(e^{\frac{2\pi i k}{n/2}}) -
= A^{[0]}(e^{\frac{2\pi i k}{n/2}}) -
e^{\frac{2\pi i k}{n}} A^{[1]}(e^{\frac{2\pi i k}{n/2}}) =  
e^{\frac{2\pi i k}{n}} A^{[1]}(e^{\frac{2\pi i k}{n/2}}) =
</math></center>
</math></center>


Linia 183: Linia 183:


Gdzie w ostatniej równości skorzystaliśmy ze wzoru
Gdzie w ostatniej równości skorzystaliśmy ze wzoru
[[wzor|wzor_1|(1)]]. Widzimy zatem, że algorytm poprawnie oblicza
[[ZASD Moduł 4#wzor_1|(1)]]. Widzimy zatem, że algorytm poprawnie oblicza
wartość STF dla wielomianu <math>A(x)</math>. Równanie rekurencyjne
wartość STF dla wielomianu <math>A(x)</math>. Równanie rekurencyjne
na czas działania procedury STF wygląda następująco:
na czas działania procedury STF wygląda następująco:

Wersja z 14:31, 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.

Algorytm Algorytm Szybkiej Transformaty Fouriera


 STF(a=(a0,,an1))
 if n nieparzyste then
   dodaj wyraz an do a
   zwiększ n
 if n=1 then return a
 ωn=e2πin
 ω=1
 a[0]=(a0,a2,,an2)
 a[1]=(a1,a3,,an1)
 y[0]=SFT(a[0])
 y[1]=SFT(a[1])
 for k=0 to n21 do
   yk=yk[0]+ωyk[1]
   yk+n2=yk[0]ωyk[1]
   \omega = \omega \omega_n
 return y

Algorytm ten najpierw oblicza SFT wielomianów A[0](x) i A[1](x) a następnie łączy te wyniki w celu wyliczenia SFT dla wielomianu A(x). Przeanalizujmy teraz wykonanie pętli. Zauważmy najpierw, że w k'tym kroku pętli mamy ω=ωnk=e2πikn=xk.. Czyli:


yk=yk[0]+xkyk[1]=A[0](e2πikn/2)+xkA[1](e2πikn/2)=
=A[0]((e2πikn)2)+xkA[1]((e2πikn)2)=A[0](xk2)+xkA[1](xk2)=A(xk),


oraz


yk+n2=yk[0]xkyk[1]=A[0](e2πikn/2)e2πiknA[1](e2πikn/2)=
=A[0](e2πi(k+n/2)n/2)+e2πik+n/2nA[1](e2πi(k+n/2)n/2)=A[0](xk+n/22)+xk+n/22A[1](xk+n/22)=A(xk+n2).

Gdzie w ostatniej równości skorzystaliśmy ze wzoru (1). Widzimy zatem, że algorytm poprawnie oblicza wartość STF dla wielomianu A(x). 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:


=1n1e2πn(jk)n1e2π(jk)n=1n11(jk)1e2π(jk)n=0.


Czyli rzeczywiście VnWn=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.