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 57: Linia 57:




Jednak aby ostatecznie otrzymać szybszy algorytm niż algorytm naiwny
Jednak aby ostatecznie otrzymać szybszy algorytm niż algorytm naiwny
musimy pokazać jak rozwiązać problem obliczania wartości wielomianu
musimy pokazać jak rozwiązać problem obliczania wartości wielomianu
w <math>n</math> punktach w czasie szybszym niż
w <math>n</math> punktach w czasie szybszym niż

Wersja z 22:43, 18 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

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 Parser nie mógł rozpoznać (nieznana funkcja „\lots”): {\displaystyle X_n = \{x_0,x_1,\lots,x_{n-1}\}} zdefiniujemy w następujący sposób:

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

Dla wielomianu A(x) definiujemy dwa nowe wielomiany A[0](x) i Parser nie mógł rozpoznać (błąd składni): {\displaystyle 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 Parser nie mógł rozpoznać (błąd składni): {\displaystyle 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:

Parser nie mógł rozpoznać (błąd składni): {\displaystyle x_i^2 = \left(e^{\frac{2\pi i}{n} \right)^2 = e^{\frac{2\pi i}{n/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, gdzie V(x0,,xn1) jest macierzą Vandermonde'a zawierającą potęgi xi

Parser nie mógł rozpoznać (nieznana funkcja „\begin{array}”): {\displaystyle \left( \begin{array}{c} A(x_0)\\ A(x_1)\\ A(x_2)\\ \vdots\\ A(x_{n-1}) \end{array} \right) = \left[ \begin{array} x_0^0 & x_0^1 & x_0^2 & x_0^3 & \hdots & x_0^{n-1} \\ x_1^0 & x_1^1 & x_1^2 & x_1^3 & \hdots & x_1^{n-1} \\ x_2^0 & x_2^1 & x_2^2 & x_2^3 & \hdots & x_2^{n-1} \\ \vdots & \vdots & \vdots & \vdots & \ddots & \vdots \\ x_{n-1}^0 & x_{n-1}^1 & x_{n-1}^2 & x_{n-1}^3 & \hdots & x_{n-1}^{n-1} \\ \end{array} \right] \left( \begin{array}{c} a_0\\ a_1\\ a_2)\\ \vdots\\ a_{n-1) \end{array} \right) }

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

V(x0,,xn1)i,j=xij.

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

Korzystając z definicji zbioru Xn otrzymujemy

Parser nie mógł rozpoznać (błąd składni): {\displaystyle V(x_0,\ldots,x_{n-1})_{i,j} = \left(e^{\frac{2\pi i}{n}\right)^j = e^{\frac{2\pi ij}{n}.}