Fast Fourier Transform voor vermenigvuldiging Michiel De Cuyper & Brent Coosemans 2016-2017 Abstract Een naı̈eve aanpak voor vermenigvuldigen van twee getallen van n cijfers levert een exponentiële complexiteit. Het zogenaamde Grade School algoritme (bij ons vaak bekend onder de naam “cijferen”) verlaagt dit naar een kwadratische complexiteit. Met behulp van de Fourier transformatie krijgen we deze complexiteit nog verder naar beneden tot O(n log n). Deze paper beschrijft wat de Fourier transformatie juist inhoudt en hoe we deze kunnen toepassen om bovenstaande complexiteit te bereiken voor het vermenigvuldigingsprobleem. Inleiding Vermenigvuldiging is een cruciale basisoperatie uit de wiskunde. Vermenigvuldigen van twee grote getallen staat centraal in enkele algoritmen die we dagdagelijks gebruiken, denk maar aan cryptografie. Aan de basis van efficiënte algoritmen voor deze grote vermenigvuldigingen ligt de Fourier Transformatie. Deze tekst beschrijft eerst intuı̈tieve methodes voor vermenigvuldigen. Vervolgens wordt de Fourier Transformatie en zijn snelle variant voorgesteld en tonen we aan dat we deze kunnen gebruiken voor het vermenigvuldigen van twee grote getallen. Uiteindelijk bewijzen we de complexitiet van de Fast Fourier Transformatie. 1 Herhaald optellen Een naı̈ve aanpak voor het vermenigvuldigen van twee getallen van n cijfers volgt uit de definitie van vermenigvuldigen. Wanneer we schrijven 5 × 3, lezen we “vijf maal drie”. We kunnen deze vermenigvuldiging dan ook berekenen door vijf keer drie te nemen. 5×3=3+3+3+3+3 = 15 Vermits een getal van n cijfers ligt tussen 10n−1 en 10n , zien we dat er minstens n10n−1 optellingen nodig zijn. Zulke complexiteit is niet aanvaarbaar voor een operatie zo elementair als vermenigvuldiging. 1 2 Grade School algoritme Een eerste oplossing is één die ons wordt aangeleerd op de lagere school en beschreven staat in figuur 1. Deze aanpak verloopt volgens het Grade School algoritme (bij ons vaak gekend als “cijferen”). Hoewel het algoritme op het eerste zicht moeilijker is dan herhaald optellen, is het aantal rekenwerk beduidend minder. Er zijn slechts 3 optellingen nodig en 9 vermenigvuldigingen van twee cijfers. Deze vermenigvuldigingen kunnen we uitvoeren in constante tijd aan de hand van een eenvoudige lookup-table. 1 4 7 61 492 560 × 23 56 38 5 88 Figuur 1: Voorbeeld van het Grade School algoritme In het algemeen kunnen we stellen dat voor het Grade School algoritme er O(n) optellingen en O(n2 ) eenvoudige vermenigvuldigen nodig zijn. 3 3.1 Fourier Transformatie Veeltermvermenigvuldiging Coëfficiëntenvorm van een veelterm We zullen veeltermen voorstellen in hun coëfficiëntenvorm. De coëfficiëntenvector a = [a0 , a1 , . . . , an−1 ] geeft aanleiding tot de veelterm p(x) = n−1 X a i xi i=0 We zien dat het evalueren van deze veelterm n vermenigvuldigingen en n − 1 optellingen vereist. Twee veeltermen vermenigvuldigen resulteert in een derde veelterm. Net zoals het vermenigvuldigen van twee getallen, heeft dit O(n2 ) complexiteit. p(x)q(x) = a0 b0 + (a0 b1 + a1 b0 )x + . . . + an−1 bn−1 x2n−2 De graad van de resulterende veelterm is 2n−2, wat resulteert in een coëfficiëntenvector van lengte 2n − 1. We voegen een nul toe aan het einde van deze vector, om voor eenvoudigheidsredenen een vector van lengte 2n te bekomen. Het padden van deze vector zal later ook duidelijke efficintievoordelen hebben. 2 Interpolatiestelling voor veeltermen Gegeven n punten in het vlak (xi , yi ) voor i = 0 . . . n − 1, met alle xi verschillend, dan bestaat er een unieke veelterm van graad n − 1 p(x) zodat p(xi ) = yi voor alle xi Wanneer we een gekende veelterm van graad n − 1 evalueren in n punten xi , vormen de combinaties van xi en yi = p(xi ) ook een unieke voorstelling van deze veelterm. We zullen deze eigenschap gebruiken om twee veeltermen p(x) en q(x) te vermenigvuldigen als volgt: • Evalueer p(x) in 2n punten • Evalueer q(x) in dezelfde 2n punten • Bereken puntsgewijs p(xi )q(xi ) • Deze 2n punten geven, omwille van de interpolatiestelling, een unieke voorstelling van het product van p(x) en q(x) Het evalueren van de bekomen 2n punten vraagt echter nog steeds O(n2 ) operaties. We hebben een complexere oplossingsstrategie die ons geen winst oplevert. We zoeken specifieke punten xi zodat we tussenuitkomsten kunnen hergebruiken om latere berekeningen te vereenvoudigen. Een van die sets specifieke punten zijn de n -de machtswortels uit één. n-de machtswortel uit één Een getal ω is een n-de machtswortel van één als voor n ≥ 2 geldt: • ωn = 1 • De getallen 1, ω, ω 2 , . . . , ω n−1 zijn verschillend. Deze getallen zijn complex en bestaan bijgevolg uit een reëel en complex deel. Bovendien bevatten ze twee eigenschappen die bijzonder nuttig blijken te zijn. Reflexiviteitsstelling geldt ω k+n/2 = −ω k Als ω een n-de machtswortel van één is, en n ≥ 2, dan De reflexiviteitsstelling laat ons toe slechts de helft van de ω te moeten bereken. De andere helft volgt immers uit de stelling. Reductiestelling Als ω een (2n)-de machtswortel uit één is, dan is ω 2 een n-de machtswortel uit één. 3 3.2 Discrete Fourier Transformatie De Discrete Fourier Transformatie (DFT) wordt gegeven door volgende formule: Xk = N −1 X xn WNkn n=0 Wn = e2πi/N WN is een N -de machtswortel uit één. De DFT transformeert een eindige rij {xn } van N getallen om naar een rij {Xk } van N complexe getallen. We zien dat de DFT van een veelterm, voorgesteld door zijn coëfficiëntenvector, gelijk is aan die veelterm geëvalueerd in opeenvolgende machten van n-de machtswortels uit één. Inverse DFT De inverse DFT laat ons toe de originele veelterm te recupereren op basis van de Xk -rij. De formule is gelijkaardig aan die van de DFT. xn = N −1 1 X Xk WN−kn N k=0 De directe berekening van de rij Xk waarden vraagt O(n2 ) optellingen en O(n2 ) vermenigvuldigingen. 3.3 Danielson-Lanczos splitsingsalgoritme Om een O(n log(n)) complexiteit te bekomen, kunnen we enkele eigenschappen van sommatie en van de n-de machtswortels uit één uitbuiten. In 1942 toonden Danielson en Lanczos aan hoe een DFT van lengte N recursief berekend kan worden met behulp van 2 DFTs van lengte N/2. Dit verloopt als volgt. Xk = N −1 X xn e2πikn/N n=0 N/2−1 = X N/2−1 x2n e2πik(2n)/N + n=0 X x2n+1 e2πik(2n+1)/N n=0 N/2−1 = X N/2−1 x2n e2πik(2n)/N + e2πik/N n=0 X x2n+1 e2πik(2n)/N n=0 N/2−1 = X N/2−1 x2n e2πikn/(N/2) + e2πik/N n=0 X x2n+1 e2πikn/(N/2) n=0 = Xke + WNk Xko Hier gebruiken we het superscript e voor de even rijwaarden en het superscript voor de oneven rijwaarden. Dankzij de reflexiviteitsstelling en de periodici- o 4 teitseigenchappen e XN/2+k = Xke o = Xko XN/2+k kunnen we dit nog verder vereenvoudigen tot Xk = Xke + WNk Xko XN/2+k = Xke − WNk Xko We splitsen onze originele rij {xn } op in de even en oneven deelrijen {x2n } en {x2n+1 }. Van deze deelrijen berekenen we de DFT en op basis van die twee DFTs kunnen we de originele DFT opstellen. De werking hiervan staat voorgesteld in figuur 2. Figuur 2: Berekenen van de DFT door opslitsen [1] We zien dat we slechts ongeveer de helft van de vermenigvuldigingen nodig hebben van de gewone aanpak, maar nog steeds O(n2 ). 3.4 Fast Fourier Transformatie We verbeterden de complexiteit van de DFT door deze in twee te splitsen. Niets houdt ons tegen van deze deelrijen ook op te splitsen. We kunnen deze deelrijen van lengte n log2 (n) keer splitsen. Door de rij achteraan met nullen te padden to, kunnen we het aantal splitsingen verhogen. Voor een rij van lengte 1 is de Fourier getransformeerde Xk waarde gelijk aan het element zelf. We kunnen de Fast Fourier transformatie gebruiken om grote getallen te vermenigvuldigen. We stellen elk getal voor als een rij, analoog aan de coëfficiëntenvector van eerder. Het getal 123 wordt dan [1, 2, 3], wat de veelterm 1 + 2x + 3x2 voorstelt. De twee veeltermen komend uit de getallen, resulteren in een veelterm van graad N − 1. We padden de coëfficiëntenvectoren achteraan met nullen 5 tot deze lengte N hebben. Van deze rijen bepalen de Fourier transformatie en die vermenigvuldigen we componentsgewijs. Uiteindelijk bepalen we de inverse Fourier transformatie om de resultaatveelterm te bekomen. Na het bepalen van de overdrachten, bekomen we een coëfficiëntenvector die het gewenste product voorstelt. 4 Complexiteit van de FFT In deze sectie tonen we aan dat de Fast Fourier transformatie in O(n log2 (n)) is. Het FFT-algoritme roept zichzelf recursief op op de helft van de originele invoer. Het samenvoegen van de resultaten kan in O(n) tijd. Bijgevolg is de complexiteit van het FFT-algoritme O(n log2 (n)). De overige stappen voor de vermenigvuldigen zorgen voor geen extra overhead. Het padden van een vector kan in O(n), het componentsgewijs vermenigvuldigen van de coëfficiëntenvectoren kan in O(n), alsook het bepalen van de overdrachten. De inverse Fourier Transformatie kan analoog gebeuren aan de Fast Fourier transformatie en gebeurt dus ook in O(n log2 (n)). Bijgevolg kunnen we concluderen dat het vermenigvuldigen van twee getallen van lengte n kan gebeuren in O(n log2 (n)) operaties. Referenties • [1] https://www.vocal.com/wp-content/uploads/2014/03/FFT.png • [2] Multiplying Huge Integers Using Fourier Transforms; Ando Emerencia • [3] Modellering en Simulatie; Ronald Cools, Wim Michiels & Giovanni Samaey 6