Zaawansowane algorytmy i struktury danych/Wykład 4
Abstrakt
Naturalna metoda dodawania dwóch wielomianów wymaga czasu , natomiast prosty algorytm mnożenia dwóch wielomianów stopnia wymaga czasu . W wykładzie tym pokażemy, jak z wykorzystaniem szybkiej transformaty Fouriera (STF), wykonać wszystkie podstawowe operacje na wielomianach w czasie większym niż o czynnik polilogarytmiczny. Pokażemy jak dla wielomianów stopnia :
- mnożyć je w czasie ,
- obliczać wielomian interpolacyjny w czasie ,
- obliczać wartość wielomianu w punktach w czasie ,
- dzielić wielomiany w czasie .
Mnożenie wielomianów w punktach
Niech i będzą wielomianami stopnia nad ciałem . Wielomiany te możemy jednoznaczne reprezentować poprzez ich wartości w punktach. Następujące twierdzenie zostało sformułowane w ramach wykładu z Metod Numerycznych.
Twierdzenie [Twierdzenie o interpolacji wielomianów]
parami różne, istnieje jedyny wielomian stopnia taki, że dla
Niech będzie ustalonym zbiorem parami różnych punktów
. Dla tego zbioru punktów
możemy wyznaczyć zbiory wartości wielomianów:
Niech będzie wynikiem mnożenia wielomianów i , mamy wtedy
.
Ponieważ stopień wielomianu jest nie większy niż to z Twierdzenia o interpolacji zbiór wartości
,
jednoznacznie wyznacza wielomian . Mając zbiory i możemy wyznaczyć zbiór w czasie . 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 punktach w czasie szybszym niż
. Podobnie musimy umieć obliczać wielomian
interpolacyjny dla danego zbioru punktów.
Szybka transformata Fouriera (STF)
Problem obliczania wartości wielomianu w 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 . 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 oraz jest parzyste. Jeżeli jest nieparzyste to dodajemy na początek jednomian 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 definiujemy dwa nowe wielomiany i Parser nie mógł rozpoznać (błąd składni): {\displaystyle A^{[1])(x)} poprzez wybranie do nich współczynników o numerach odpowiednio parzystych i nieparzystych:
,
.
Wielomiany Parser nie mógł rozpoznać (błąd składni): {\displaystyle A^{[0](x)} oraz są stopnia co najwyżej . Co więcej zachodzi:
(1).
Widzimy teraz, że problem ewaluacji wielomianu w punktach sprowadza się do:
- ewaluacji wielomianów i
w punktach
.
- a następnie obliczenie wartości 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 , a więc . Udało nam się więc zredukować problem rozmiaru --- obliczenia wartości wielomianu stopnia w do punktach, do dwóch problemów rozmiaru --- obliczenia wartości wielomianów i stopnia w 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:
.
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 . Obliczenie wykonane w czasie szybkiej transformaty Fouriera możemy przedstawić w postaci macierzowej jako mnożenie macierzy przez wektor , gdzie jest macierzą Vandermonde'a zawierającą potęgi
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 dany jest jako
.
W celu wykonania operacji odwrotnej do SFT, czyli obliczenia wielomianu interpolacyjnego, musimy wykonać mnożenie .
Korzystając z definicji zbioru 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}.}