Algoritminen matematiikka
|
|
|
- Outi Saarinen
- 10 vuotta sitten
- Katselukertoja:
Transkriptio
1 Algoritminen matematiikka Luentomoniste Turun yliopisto Matematiikan laitos Turku 2011
2 i Alkusanat Kurssin tarkoituksena on algoritmisen ajattelun omaksuminen ja kehittäminen. Tavanomaisesti matematiikassa kysytään Onko jokin väittämä tosi? tai Onko jokin olemassa? mutta tällä kurssilla tarkastellaan lähinnä kysymystä Miten tämä jokin voidaan laskea ja kuinka nopeasti?. Tietotekniikan myötä algoritmisesta matematiikasta on tullut hyvin tärkeä osa matematiikkaa. Laskentaa, ja osin jopa todistamista, suoritetaan tietokoneilla. Monilla soveltavilla matematiikan aloilla, kuten esimerkiksi kryptograssa, algoritminen ajattelu on välttämätöntä. Kurssilla keskitytään tavanomaisten aritmeettisten ja lukuteoreettisten ongelmien laskennallisen kompleksisuuden arviointiin, ja erityisesti siihen miten nämä probleemat tulee nähdä algoritmisesta näkökulmasta ts. mitä voidaan laskea nopeasti, siis käytännössä, ja mitä ei voida (nykytiedon perusteella). Kurssin esitiedoiksi tarvitaan Algebran peruskurssi I:n tai Kryptograan matemaattiset perusteet kurssien antamia lukuteorian perustietoja. Tämä moniste perustuu suurelta osin Turun yliopiston matematiikan laitoksen luentomonisteeseen vuodelta Tämän lisäksi lähteenä on käytetty seuraavia lähteitä: 1. G. Brassard, P. Bratley: Fundamentals of Algorithmics, Prentice Hall, T. Cormen, C. Leiserson, R. Rivest, C. Stein: Introduction to Algorithms, MIT Press, 2001 (2nd ed.). 3. J. von zur Gathen, J. Gerhard: Modern Computer Algebra, Cambridge University Press, 2003 (2nd ed.).
3 1 1 Johdanto 1.1 Algoritmien tutkimus Algoritmi on konstruktiivisen ja diskreetin matematiikan keskeisimpiä käsitteitä. Implisiittisesti algoritmit ovat olleet osa matematiikkaa kautta sen koko historian. Vanhin ja ehkä tunnetuin algoritmi Eukleideen algoritmi on yli 2000 vuotta vanha. Sen laskennallisen kompleksisuuden arviointi vuodelta 1845 (Lame) puolestaan on yksi vanhimmista konkreettisista algoritmiteorian tuloksista. Varsinaisesti algoritmien tutkimus käynnistyi 1930luvulla teoreettisena Laskettavuuden teorian (ala I, alla) tutkimuksella. Käytännön läheisempää tutkimus oli 1950luvulla jolloin keskityttiin Algoritmien suunnitteluun ja analysointiin (ala II). Viime aikoina, 1970luvulta lähtien Kompleksisuusteorian tutkimus (ala II) on ollut keskeisessä asemassa. Kompleksisuusteoriassa tutkitaan esimerkiksi, mitkä probleemat ovat käytännössä algoritmisesti ratkaistavissa polynomiajassa toimivalla algoritmilla tai onko probleemalle olemassa nopeaa todennäköisyysalgoritmilla. Yllä mainituista kolmesta algoritmitutkimuksen alasta käytetään yleensä alla esitetyn mukaisia nimityksiä, niinikään alla esitetään alojen tutkimusten tarjoama keskeinen anti. I: Laskettavuuden teoria; Algoritmisesti ratkeamattomat probleemat, Turingin koneet III: Algoritmien suunnittelu ja analysointi; Monet tärkeät nopeat käytännön algoritmit II: Kompleksisuusteoria; Käytännössä mahdottomat probleemat (nykytiedon mukaan); P? = N P -probleema; todennäköisyysalgoritmit Laskettavuuden teoria mullisti matemaattisen ajattelun, kun K. Gödel vuonna 1936 osoitti, että on olemassa algoritmisesti ratkeamattomia probleemoja. Nimittäin vielä vuosisadan vaihteen matemaatikot, kuten Hilbert,
4 1.1 Algoritmien tutkimus 2 ajattelivat, että kaikki mielekkäästi määritellyt probleemat ovat ainakin periaatteessa (vaikkakaan ei välttämättä käytännössä) algoritmisesti ratkaistavissa. Kompleksisuusteoria puolestaan on osoittanut, että monet käytännössä tärkeät probleemat, kuten esimerkiksi lukujärjestyksen laatiminen, ovat käytännössä mahdottomia ratkaista (ts. niiden ratkaiseminen vaatii liikaa resursseja), vaikkakin matemaattisesti niiden ratkaiseminen voi olla triviaalia (esim. käydään läpi kaikki vaihtoehdot). Tässä on syytä korostaa, että käytännössä mahdoton tarkoittaa: käytännössä mahdoton nykytiedon mukaan. Se, ovatko kyseessä olevat probleemat todella käytännössä mahdottomia, on yksi modernin matematiikan suurista avoimista kysymyksistä, ns. P? = N P -probleema. Tämän kurssin tarkoituksena on toimia johdatuksena algoritmiseen ajatteluun. Tähän pyritään tarkastelemalla konkreettisten, lähinnä aritmeettisten probleemojen laskennallista vaikeutta. Tarkasteltaviin ongelmiin pyritään etsimään tehokkaita algoritmeja. Siten yllä olevan luokittelun valossa kurssi kuuluu lähinnä alueelle III. Mainittakoon lopuksi, että termi algoritmi juontaa juurensa persialaisesta matemaatikosta Mohammed al-khowârizmî 800-luvulta. Hän kehitti algoritmiset säännöt lukujen aritmeettisten operaatioiden laskemiseksi: samat, jotka ovat yhä käytössä kouluopetuksessa.
5 3 2 Algoritmien peruskäsitteitä 2.1 Esimerkki Tarkastellaan kahden positiivisen kokonaisluvun tulon laskemista. Aikojen kuluessa on kehitetty useita erilaisia menetelmiä tämän ongelman ratkaisemiseksi. Mielivaltaisen suurten lukujen tulo opitaan laskemaan jo koulun alaluokilla. Klassinen koulualgoritmi palauttaa pidempien lukujen tulon laskemisen 1-numeroisten lukujen tuloihin, jotka puolestaan muistetaan ulkoa opituista kertotauluista. Ns. arabialaisessa kertoalgoritmissa käytetään apuna laatikkoa, jonka sivujen pituudet ovat samat kuin kerrottavien lukujen pituudet. Kerrottavat luvut asetetaan laatikon sivuille, ja laatikkoon kirjataan kaikkien luvuissa esiintyvien numeroiden tulot oheisen kuvan osoittamalla tavalla. Lukujen tulo saadaan puuttuville sivuille laskemalla diagonaalien summat. Kaksi edellä mainittua menetelmää muistuttavat kovasti toisiaan, mutta venäläisessä kertoalgoritmissa asia ratkaistaan toisin. Siinä toista kerrottavista luvuista toistuvasti puolitetaan (pyöristämällä alaspäin) ja toista tuplataan, kunnes puolitettava luku on ykkönen. Lukujen tulo saadaan ynnäämällä ne tuplatut luvut, joita vastaava puolitettu luku on pariton. Mikä yllä esitetyistä menetelmistä on paras? Jotta tähän voitaisiin vastata, tarvitaan jokin hyvyyden mittari. Tällä kurssilla eri laskentamenetelmiä vertaillaan niiden tehokkuuden, siis nopeuden, perusteella. Osoittautuu, että tässä mielessä kaikki edellä esitetyt algoritmit ovat asymptoottisesti yhtä hyviä. a) b) c) Kuva 1: a) Klassinen, b) arabialainen ja c) venäläinen kertolaskualgoritmi. Esitetään vielä yksi kertolaskualgoritmi. Siinä kerrottavien lukujen a ja b pituus n pitää olla jokin kakkosen potenssi: n = 2 m (jos näin ei ole, lukujen eteen voidaan lisätä tarvittava määrä nollia). Olkoon a = a 1 10 n/2 + a 0 ja b = b 1 10 n/2 + b 0, missä 0 a 0, a 1, b 0, b 1 < 10 n/2. Nyt ab = a 1 b 1 10 n + (a 0 b 1 + a 1 b 0 ) 10 n/2 + a 0 b 0,
6 2.2 Algoritmi ja algoritminen probleema 4 joten kahden luvun tulo saadaan laskemalla neljä puolta lyhyempien lukujen tuloa (ja lisäksi muutamia yhteenlaskuja ja kymmenellä kertomisia). Nämä pienemmät tulot voidaan edelleen laskea samalla menetelmällä. Näin saadaan rekursiivinen kertolaskualgoritmi, jossa 2 i -numeroisten lukujen tulo saadaan laskemalla (2 i ) 2 1-numeroisten lukujen tuloa. Osoittautuu, ettei tämäkään rekursiivinen algoritmi ole sen tehokkaampi kuin aiemmin mainitut menetelmät. Mutta kuten myöhemmin nähdään, ideaa voidaan parannella niin, että tulon laskeminen palautuukin kolmen (eikä neljän) puolta lyhyemmän luvun tuloon. Tuloksena on merkittävästi nopeampi algoritmi, etenkin jos tarkasteltavat luvut ovat suuria. 2.2 Algoritmi ja algoritminen probleema Algoritminen probleema koostuu syötteistä I ja kuhunkin syötteeseen liittyvästä (usein yksikäsitteisestä) tulosteesta. Probleema voidaan siis ajatella funktiona I O, missä O on kaikkien mahdollisten tulosteiden joukko. Algoritmi on puolestaan menetelmä, jolla tarkasteltava probleema voidaan mekaanisesti ratkaista. Voidaan siis sanoa, että algoritmi on metodi yllä mainitun funktion I O laskemiseksi. Jos tehtävänä on ratkaista probleema jollakin tietyllä syötteellä, puhutaan probleeman instanssista. Esimerkiksi kahden positiivisen kokonaisluvun kertolasku on algoritminen probleema, ja se voidaan ratkaista millä tahansa alun esimerkissä mainitulla algoritmilla. Ongelman syötteet ovat siis kokonaisluku pareja ja parin (123, 45) tulon laskeminen on yksi tämän probleeman instansseista. Yleensä algoritmilta vaaditaan seuraavia ominaisuuksia. (i) Algoritmin suoritus koostuu joukosta peräkkäin suoritettavia yksinkertaisia operaatioita, ns. alkeisoperaatioita. (ii) Algoritmin ohjeita sovelletaan deterministisesti, ts. algoritmin suoritus etenee samalla syötteellä aina tarkalleen samalla tavalla. (iii) Algoritmin ohjeet ovat universaalisia; ts. algoritmi ratkaisee ongelman kaikilla mahdollisilla syötteillä. (iv) Algoritmin ohjeet ovat terminoivia; ts. kullakin syötteellä tarvitaan vain äärellinen määrä alkeisoperaatioita. Tosin käyttökelpoisia käytännön laskentamenetelmiä voidaan saada, vaikka kohdasta (ii) tingittäisiinkin, esim. myöhemmin käsiteltävät todennäköisyys algoritmit. Algoritmiset probleemat, joiden vastaus on aina joko kyllä tai ei (tai 1/0) ovat algoritmien teorian kannalta erityisen tärkeitä. Tällaisia probleemoja kutsutaan päätäntäongelmiksi tai vaihtoehtoisesti ratkeavuusongelmiksi. Esimerkiksi probleema, jossa kysytään, onko syötteenä saatu luku alkuluku vai ei, on päätäntäongelma.
7 2.3 Syöte ja alkeisoperaatiot Syöte ja alkeisoperaatiot Algoritmien tehokkuutta mitataan sen syötteen s koon, merk. s l, funktiona. Syötteen koko voidaan tapauksesta riippuen määritellä hieman eri tavoin, mutta intuitiivisesti se yleensä ilmoittaa sen, paljonko tilaa (tai tietokoneen muistia) tarvitaan syötteen esittämiseen. Esimerkiksi kokonaislukusyötteen kooksi on luonnollista määritellä luvun pituus. Mutta esimerkiksi n nmatriisin kooksi ajatellaan yleensä n (eikä n 2 ). Saatuaan syötteen s algoritmi suorittaa alkeisoperaatioita niin kauan, kunnes tuloste saadaan. Se, mitä alkeisoperaatioilla tarkoitetaan, vaihtelee tarkasteltavan probleeman mukaan. Esimerkiksi kertoalgoritmeissa 1-numeroisten lukujen tulon (ja summan) laskeminen ajatellaan alkeisoperaatioksi. Joissakin lajittelualgoritmeissa kahden luvun suuruuden vertailu katsotaan alkeisoperaatioksi. Sen sijaan algoritmin ohjauskäskyjä ei ole tapana laskea alkeisoperaatioiksi. Ideana on, että yhden alkeisoperaation suorittaminen onnistuu aina vakioajassa ja että algoritmin suoritusaika on suoraan verrannollinen suoritettujen alkeisoperaatioiden määrään. 2.4 Algoritmin kompleksisuus Tarkasteltava ongelma voidaan (ainakin useimmiten) ratkaista useilla erilaisilla algoritmeilla. Tällöin on luonnollista kysyä: Mikä ongelman ratkaisevisista algoritmeista on paras? Tällä kurssilla algoritmeja vertaillaan lähinnä niiden nopeuden perusteella. Nopeus puolestaan mitataan laskemalla, kuinka monta alkeisoperaatiota algoritmin suorittaminen vaatii. Olkoon T A,s algoritmin A suorittamien alkeioperaatioiden määrä syötteellä s. Syötteen s koko s on luonnollinen luku, ja algoritmin A kompleksisuus määritellään funktiona T A : N N, T A (n) = max s l =n {T A,s}. T A (n) siis kertoo, kuinka nopeasti tuloste varmasti saadaan kaikilla n-kokoisilla syötteillä. Toisinaan tätä kutsutaan pahimman tapauksen kompleksisuudeksi. Usein parempi mittari algoritmin tehokkuudelle olisi keskimääräinen kompleksisuus. Se on kuitenkin lähes aina paljon vaikeampi laskea. Yllä tarkasteltiin algoritmissa tarvittavien laskuaskelien määrää, siis aikakompleksisuutta. Yhtä hyvin voitaisiin tarkastella vaikka algoritmin vaatimien muistipaikkojen määrää, eli tilakompleksisuutta. Tällä kurssilla kompleksisuudella tarkoitetaan aina aikakompleksisuutta.
8 2.4 Algoritmin kompleksisuus 6 Yllä kompleksisuuskäsitteet määriteltiin algoritmeille. Käsitteet voidaan laajentaa koskemaan myös tarkasteltavaa algoritmista probleemaa. Probleeman AP kompleksisuus on sen parhaan ratkaisualgoritmin kompleksisuus. Tässä paras tarkoittaa asymptoottisesti nopeiten toimivaa algoritmia. Algoritmin kompleksisuuden analysointi tarkoittaa sen kompleksisuuden (tai oikeastaan sen kertaluvun, suuruusluokan) määräämistä. Tämä on useimmiten mahdollista suorittaa tekemällä esim. sopivia arviointeja. Sen sijaan algoritmisen probleeman AP kompleksisuuden (kertaluvun) määrääminen on usein ylivoimaisen vaikeaa. Mikä tahansa AP:n ratkaiseva algoritmi antaa ylärajan AP:n kompleksisuudelle, mutta hyvien alarajojen määrääminen on yleisesti algoritmien teorian vaikeimpia asioita. Pitäisi nimittäin osoittaa, että mikään algoritmi ei ratkaise AP:ta annettua funktiota nopeammin. Esimerkki 2.1. Tämän luvun alussa tarkasteltiin kokonaislukujen kertolaskun laskevia algoritmeja. Voidaan osoittaa, että esitetyt algoritmit toimivat ajassa O(n 2 ) (ordo-merkintä), mikä tarkoittaa, että on olemassa positiivinen luku α ja luonnollinen luku n 0 joille tiedetään, että kaikille n n 0 T A (n) αn 2. Tästä seuraa, että algoritmisen probleeman kompleksisuus on myöso(n 2 ). Toisaalta, myöhemmin tällä kurssilla osoittautuu, että kertolasku-probleeman algoritminen kompleksisuus on O(n(log n) 2+ε ), koska on olemassa algoritmi, joka toimii ajassa O(n(log n) 2+ε ). Todettakoon vielä, että paras tunnettu kertolaskualgoritmi toimii ajassa O(n log n log log n) ajassa (Schönhage and Strassen 1971, Knuth 1998). Algoritmit ja algoritmiset probleemat jaetaan tavallisesti kahteen luokkaan, missä rajan määrää polynomiaikaisuus. Algoritmia A kutsutaan toteutettavaksi (feasible), jos on olemassa sellainen polynomi P (n), että T A (n) P (n) jostakin rajasta n n 0 lähtien. Muussa tapauksessa algoritmia sanotaan eitoteutettavaksi (infeasible). Algoritmista probleemaa AP kutsutaan ratkaistavaksi (tractable), jos AP:lle tunnetaan toteuttava ratkaisu; muuten AP:ta sanotaan eiratkaistavaksi (intractable). Usein ajatellaan, että ratkaistavat probleemat ovat helppoja ja siten käytännössä ratkeavia. Kirjaimellisesti tämä ei tietysti pidä paikkaansa, mutta luokittelu on teoreettisesti perusteltua, ja itse asiassa yleensä polynomiaikaiset algoritmit toimivat alhaista astetta olevassa polynomiajassa. Toisaalta eiratkaistavien probleemien vähänkin suuremmat instanssit ovat varmasti käytännössä mahdottomia ratkaista ainakin tällä hetkellä.
9 2.5 Funktion kertaluku Funktion kertaluku Esimerkki 2.2. Alla on taulukoitu algoritmin vaatima aika, kun oletetaan yhden alkeisoperaation suorittamisen kestävän yhden nanosekunnin (10 9 s) verran. n = 10 n = 20 n = 30 n = 50 n = 100 n = 1000 n 0,01 µs 0,02 µs 0,03 µs 0,05 µs 0,10 µs 1,00 µs n log 2 n 0,03 µs 0,09 µs 0,15 µs 0,28 µs 0,66 µs 9,97 µs n 2 0,10 µs 0,40 µs 0,90 µs 2,50 µs 10 µs 1000 µs n 5 0,10 ms 3,20 ms 24,3 ms 0,31 s 10,0 s 11,6 vrk 2 n 1,0 µs 1,0 ms 1,07 s 13,0 vrk 3000 mki mki 3 n 59,0 µs 3,5 s 2,4 vrk v mki... Nähdään, että jos kompleksisuus on eksponentiaalinen (kaksi viimeistä riviä), kasvaa algoritmin suoritusaika vähänkin isommilla instasseilla käsittämättömän suureksi (yksikkö mki tarkoittaa maailmankaikkeuden ikää). Jos kompleksisuus on polynomiaalinen, ei vastaavaa ilmiötä esiinny. Tarkastellaan vielä teknologian kehittymisen tuomia mahdollisuuksia. Seuraavasta taulukosta nähdään tietokoneiden nopeutumisen vaikutukset suurimpaan ongelmakokoon, joka ratkeaa jossakin annetussa ajassa (esim yhdessä tunnissa). kompl. nykykoneet 100 nykykone 10 6 nykykone n N N N 1 n log 2 n N 2 = N N 2 n 2 N 3 10 N N 3 n 5 N 4 2,5 N 4 16 N 4 2 n N 5 N 5 + 6,6 N ,9 3 n N 6 N 6 + 4,2 N ,6 Kahden viimeisen sarakkeen luvut kertovat sen ongelmakoon, joka ratkeaa samassa ajassa, kun käytössä on sata/miljoona kertaa tehokkaampi tietokone. Taas ero polynomiaikaisten ja eksponentiaalisten algoritmien välillä on räikeä. Eri algoritmeja verratessa olennaisinta on, kuinka kompleksisuus muuttuu, kun ongelmakoko kasvaa yhä suuremmaksi. Sitä varten otetaan käyttöön seuraavat merkinnät. Olkoot f, g : N R +. Määritellään f(n) = O(g(n)), joss α > 0, n 0 n n 0 : f(n) α g(n), f(n) = Ω(g(n)), joss β > 0, n 0 n n 0 : f(n) β g(n), f(n) = Θ(g(n)), joss α, β > 0, n 0 n n 0 : β g(n) f(n) α g(n), f(n) = o(g(n)), joss lim n f(n) g(n) = 0, f(n) g(n), joss lim n f(n) g(n) = 1.
10 2.5 Funktion kertaluku 8 Tarkkaan ottaen esimerkiksi O ( g(n) ) on luokka funktioita, ja merkintä f(n) = O ( g(n) ) Tarkoittaa, että f(n) kuuluu luokkaan O ( g(n) ). Esimerkki 2.3. Seuraavat väitteet ovat suhteellisen helppoja todistaa: a 0 + a 1 n a k n k = Θ(n k ), missä a k > 0 n a = o(n b ), kun a, b R ja 0 < a < b log c n = Θ(log d n) (c, d > 1) log c n = o(n a ) (c > 1, a > 0) Tässä monisteessa sovitaan, että jos logaritmien kantalukua ei mainita, tarkoitetaan aina 2-kantaista logaritmia: log n = log 2 n. Yllä olevasta seuraa mm., että log c n = Θ(log n) kaikilla kantaluvuilla c. Esimerkki 2.4. Esitetään tyypillinen menetelmä summalausekkeen asymptoottisen kertaluvun määräämiseksi. Osoitetaan, että S(n) = n i k = Θ(n k+1 ). i=1 Tämä voidaan todistaa näyttämällä, että S(n) = O(n k+1 ) ja että S(n) = Ω(n k+1 ). Koska i k < n k, kun 1 i n, niin S(n) n n k = n n k = n k+1. i=1 Siis S(n) = O(n k+1 ). Ω-suuntaan todistus on lähes yhtä helppo. Nyt arvioimalla 0 i k kun i n 2 ja ( n 2 )k i k kun i n 2 saadaan n S(n) ( n 2 )k n 2 (n 2 )k = 1 2 k+1 nk+1. i= n 2 Näin ollen myös S(n) = Ω(n k+1 ).
11 2.5 Funktion kertaluku 9 Jos F on luokka funktioita N R +, niin luokka O(F) on luonnollista määritellä ehdosta O(F) = O(f). f F Vastaavasti funktioille määritellyt operaatiot voidaan laajentaa joukoille luonnollisella tavalla; esimerkiksi g + F = {g} + F = {g + f} f F g(f) = g f. ja f F Tällöin yhdistämällä asymptoottisia luokkia O, Ω ja Θ sekä funktioiden operaatioita, kuten + ja voidaan määritellä uusia funktioluokkia. Esimerkki 2.5. Voidaan osoittaa, että ( O f(n) + O ( g(n) )) = O ( f(n) + g(n) ) = O ( max{f(n), g(n)} ) ; ( ) n 1 + O(1) = 2 O(n) = O(α n ). Mainittakoon, että niiden päätösongelmien joukkoa, joiden kompleksisuuden ylärajana on luokkaan 2 O(n) kuuluva funktio, merkitään EX P, siis eksponentiaalisessa ajassa ratkeavat ongelmat. Polynomiajassa ratkeavien (kompleksisuuden ylärajana jokin polynomi) päätösongelmien joukkoa merkitään P:llä. Tällä kurssilla luokkia O ( f(n) ) jne. ajatellaan algoritmisina kompleksisuusluokkina, joten f(n) on tavallisesti varsin siististi käyttäytyvä; esimerkiksi muotoa α 1 n k, n log n, log log n, a n, n log n. Tällä kurssilla käsitellään algoritmien kompleksisuuksia, joten yleensä tarkasteltavien funktioiden arvot kasvavat kun syötteen koko kasvaa. Siksi tarkasteltavat funktiot ovat eivähenevä tai ainakin lopulta eivähenevä, siis eivähenevä jostakin n:n arvosta alkaen. Määritelmä 2.1. Olkoon f : N R + lopulta eivähenevä ja b 2 kokonaisluku. Sanotaan, että f on b-sileä, jos f(b n) = O ( f(n) ). Usein algoritmien kompleksisuuden arviointi on helpompaa, jos syötteen pituus on jotakin sopivaa muotoa. Jos esimerkiksi rekursiivinen algoritmi jakaa n-pituisen syötteen aina n 2 - ja n 2 pituisiin osiin, ovat kompleksisuustarkastelut luultavasti helpompia, jos n on jokin kakkosen potenssi. (Silloinhan osat ovat aina yhtä suuret ja myös osien koot ovat kakkosen potensseja) Osoitetaan seuraavaksi, että yleensä voidaan olettaa, että syötteen pituus on sopivaa muotoa. Määritellään ensin ehdolliset kompleksisuusluokat.
12 2.6 Algoritmien kuvauksesta 10 Määritelmä 2.2. Funktio f kuuluu luokkaan O ( g(n) ; P (n) ), jos n 0, α > 0 : ( P (n) on tosi n n 0 ) = f(n) α g(n). Lemma 2.1. Olkoon p 2 kokonaisluku ja g(n) p-sileä sekä f(n) lopulta eivähenevä. Silloin f(n) = O ( g(n) ; n on p:n potenssi ) = f(n) = O ( g(n) ). Todistus. Olkoon n = p m + n, missä 0 n < (p 1)p m. Silloin f(n) a f ( p m + (p 1)p m) = f(p m+1 ) b α 1 g(p m+1 ) c α 1 α 2 g(p m ) d α g(n). Kun oletetaan, että argumentti on riittävän suuri, seuraavat arviot ad siitä, että a) f on lopulta eivähenevä; b) f(n) = O ( g(n) ), kun n on p:n potenssi; c) g on p-sileä; ja d) g on lopulta ei-vähenevä. Yllä olevissa tarkasteluissa, erikoisesti edellisessä lemmassa, O voidaan korvata symbolilla Ω tai Θ. 2.6 Algoritmien kuvauksesta Tässä monisteessa osa algoritmeista kuvataan pelkästään sanallisesti vain oleellisimat seikat mainiten. Joissakin tapauksissa taas annetaan tarkempi kuvaus, joka on helpompi muuntaa vaikka tietokoneohjelmaksi. Koska algoritmin tulee ratkaista ongelma kaiken kokoisilla syötteillä, tarvitaan joitakin lyhennysmerkintöjä. Alla on mainittu käytetyn pseudokoodin yleisimmät käskyt. Toistorakenteet: for i = 1 to n do... repeat... until lopetetaan while jatketaan do... Haaraumat: if... then (... else... ) Aliprosessien kutsut (mukaanlukien rekursiot)
13 2.7 Esimerkkejä 11 Lopetuskäskyt: return (vastaus) quit Käskyjen merkitykset lienevät ilmeisiä. Merkintä x α tarkoittaa, että muuttujan x arvoksi asetetaan α. Lisäksi yleensä ajatellaan, että syötteen pituus, jota merkitään useimmiten parametrillä n, on tiedossa. Esimerkiksi alla on alun esimerkissä mainitun venäläisen kertoalgoritmin kuvaus. Algoritmi 2.1. Venäläinen kertoalgoritmi. syöte: kokonaisluvut a, b > 0 tuloste: tulo ab x 0 while a > 0 do if a on pariton then x x + b a a 2, b 2b return x 2.7 Esimerkkejä Kerrataan vielä määritelmiä ja termejä muutaman esimerkin kautta. Esimerkki 2.6. Tarkastellaan probleemaa Prime(a), joka päättää, onko syötteenä saatava positiivinen kokonaisluku a alkuluku vai ei. Tällä probleemalla on triviaali ratkaisu: for i = 2 to a do testaa jakaako i luvun a Jaollisuustestit voidaan tehdä tavallisella jakoalgoritmilla. Jos luvun a pituus binäärilukuna on n (siis 2 n 1 a < 2 n ), niin tavanomaisen jakoalgoritmin kompleksisuus on O(n 2 ). Testijakojen tekeminen on siis nopeaa. Testejä pitää kuitenkin tehdä O( a) = O(2 n/2 ) kertaa, joten algoritmin kompleksisuus on eksponentiaalinen. Yleisemminkin, jos syötteenä on npituinen kokonaisluku a ja jotain operaatiota täytyy toistaa k a kertaa, on algoritmin kompleksisuus aina eksponentiaalinen: a = 2 n/k. Suurilla n:n arvoilla tällaiset algoritmit ovat k käyttökelvottomia. Mainittakoon, että Primeprobleema on yksi tutkituimpia matemaattisia ongelmia. Sille löydettiin polynomiaikainen algoritmi vasta vuonna Primeprobleemaa käsitellään tarkemmin myöhemmin tällä kurssilla.
14 2.7 Esimerkkejä 12 Esimerkki 2.7. Tarkastellaan probleemaa Fibonacci(n), jossa tehtävänä on laskea Fibonaccin luku F n. Fibonaccin luvuthan määritellään ehdoista F 0 = 0, F 1 = 1,. F n+2 = F n+1 + F n, kun n 0 Esitetään neljä menetelmää probleeman ratkaisemiseksi. A) Lasketaan F n kaavasta F n = a α n + b β n missä α = 1 2 (1+ 5) ja β = 1 2 (1 5) sekä a ja b R ovat vakioita (ja voidaan laskea rekursion alkuarvoista). Kaava voidaan todistaa vaikka induktiolla. B) Lasketaan F n rekursiivisesti algoritmilla Fibo(n): if n = 0 tai n = 1 then return F 0 = 0 tai F 1 = 1 else x Fibo(n 2), y Fibo(n 1) return F n = x + y C) Lasketaan F n seuraavasti: if n = 0 tai n = 1 then return F 0 = 0 tai F 1 = 1 else x 0 ja y 1 for i = 2 to n 1 do s x + y, x y, y s return F n = x + y D) Määritellään E = ( ), lasketaan matriisi En+1 ja tulostetaan sen paikassa (1, 1) oleva alkio. Selvästi algoritmit B ja C toimivat oikein. Algoritmin D:n oikeellisuus seuraa kaavasta E n+1 = F n F n+1, F n+1 F n+2 mikä nähdään oikeaksi induktiolla. Arvioidaan seuraavaksi tarvittavien aritmeettisten operaatioiden määrää yllä olevissa algoritmeissa. Algoritmi A vaatii, ainakin tavanomaisesti toteutettuna, Θ(n) aritmeettista operaatiota reaaliluvuilla. Siis vaikka tulos on kokonaisluku, laskut suoritetaan reaaliluvuilla. Siksi laskun tulos on aina vain likiarvo ja vasta virhetarkastelun jälkeen voidaan olla varmoja tuloksen oikeellisuudesta. Algoritmi ei ole algoritmisesti selkeä.
15 2.7 Esimerkkejä 13 joten Merkitään algoritmin B kompleksisuutta T :llä. Silloin T (0) = T (1) = 0 ja T (n) = T (n 1) + T (n 2) + 1, T (n) F n 1 ( n 2). Näin ollen T (n) = Ω(α n ), missä α = 1 2 ( 5 + 1) > 1, ja algoritmin kompleksisuus on eksponentiaalinen. Algoritmi C puolestaan suorittaa kussakin for silmukassa vain yhden aritmeettisen operaation, joten sen kompleksisuus on Θ(n). On syytä huomata, että vaikka tässä laskettaisiin kaikki toiminnot, kuten esimerkiksi testaus n? = 0, asetukset x y, indeksimuuttujan i kasvattaminen jne., niin kompleksisuus säilyisi luokassa Θ(n). Algoritmissa D ongelma ratkeaa laskemalla matriisin E potensseja. Myöhemmin tullaan näyttämään, että luvun a potenssin a n laskeminen onnistuu Θ( n l ):lla kertolaskulla. Aivan samoin matriisin n:s potenssi voidaan laskea käyttäen Θ( n l ) matriisien kertolaskua. Yksi 2 2matriisien tulo vaatii vakiomäärän (12 kpl) aritmeettisia operaatioita, joten tämän algoritmin kompleksisuus on Θ( n l ) = Θ(log n) aritmeettista operaatiota. Yllä laskettiin eri algoritmien vaatimia aritmeettisia operaatioita n:n funktiona, missä on siis luku n, jota vastaava luku F n pitää laskea. Syötteen koko on siis tässä tapauksessa luvun n pituus, joka on siis log n. Algoritmi D oli niistä (asymptoottisesti) paras, se vaati vain lineaarisen määrän operaatioita syötteen n pituuden log n suhteen. Nämä ovat kuitenkin minkä tahansa pituisten lukujen aritmeettisia operaatioita. Nimittäin, ns. bittioperaatiota, eli 1numeroisten lukujen aritmeettisia operaatioita, tarkastellessa huomataan, että itse asiassa mikään algoritmi ei voi toimia polynomiajassa. Tämä johtuu siitä, että Fibonaccin luvut ovat eksponentiaalisen pitkiä luvun n pituuden suhteen. Näin ollen jo pelkkä vastauksen tulostaminen vie eksponentiaalisen ajan. Esimerkki 2.8. Tarkastellaan niin sanottua Collatzin probleemaa. Kutakin luonnollista lukua n kohden määritellään jono (a j ) j=0 ehdosta n jos j = 0 a j = a j 1 /2 jos a j 1 on parillinen. 3a j jos a j 1 on pariton Olkoon f funktio, joka määritellään ehdosta Onko f algoritmisesti laskettavissa? f(n) = min{j a j = 1}.
16 2.7 Esimerkkejä 14 Jonon (a j ) määrittelyn perusteella on helppoa laatia ratkaisumenetelmä, joka saatuaan syötteen n laskee peräkkäin lukuja a j ja tulostaa ensimmäisen j:n, jolle a j = 1. Menetelmää voi kutsua algoritmiksi, jos kyseinen j on aina olemassa. Mutta ei tiedetä, onko kaikilla n:n arvoilla olemassa tällainen j. Algoritmin määritelmän kohdan (iv) nojalla ei tiedetä, onko f hyvin määritelty algoritminen probleema, tai sen laskeva algoritmi määritelmän mukainen algoritmi. Jos algoritmin määritelmästä unohdetaan kohta (iv), saadaan ns. puolialgoritmi. Edellä siis kuvattiin puolialgoritmi funktion f laskemiseksi. Kysymys terminoiko annettu puolialgoritmi annetulla syötteellä on yleisesti erittäin vaikea kysymys. Esimerkki 2.9. Olkoon ρ [0, 1] reaaliluku. Liitetään lukuun ρ algoritminen probleema P ρ, missä tehtävänä on syötteellä n laskea ρ:n n:s desimaali. Algoritmisena probleema P ρ on hyvin määritelty. Mutta onko sillä ratkaisua; ts. onko olemassa algoritmia, joka ratkaisee P ρ :n? Vastaus riippuu luvun ρ valinnasta. Esimerkiksi tapauksissa ρ = 1 2 tai ρ = 2 3 vaadittu algoritmi on helppo antaa. Näin on yleisemminkin aina, kun ρ Q, vaikka perustelu onkin hieman hankalampi. Mutta suurimmalle osalle ρ:n valintoja vastaus on kielteinen, sillä välin [0, 1] reaalilukujen kardinaliteetti on ylinumeroituva; mutta algoritmeja on vain numeroituva määrä. Jälkimmäinen väite seuraa siitä, että algoritmi koostuu aina äärellisestä määrästä äärellisiä ohjeita. Siispä algoritmeilla on aina äärellinen deskriptio esimerkiksi suomen kielen lauseina. Kaikki äärelliset lauseet voidaan asettaa jonoon vaikka pituuden mukaan järjestettynä, samanpituiset aakkosjärjestykseen. Yllä oleva osoittaa, että valtaosa reaaliluvuista on algoritmisen matematiikan saavuttamattomissa.
17 15 3 Aritmeettisia peruslaskutoimituksia Tässä luvussa tarkasteltavat probleemat ovat hyvin tuttuja kokonaislukujen aritmeettisia laskutoimituksia ja niiden laskennallista kompleksisuuden määrääminen. Nähdään, että jotkut probleemat voidaan ratkaista eitriviaalilla metodilla yllättävän nopeasti. Pohditaan aluksi, missä muodossa algoritmit saavat kokonaislukusyötteensä. Tietokoneissa, joissa on l-bittinen prosessori, esitetään kokonaisluku a vektorina [b, a 0, a 1,..., a n 1 ], missä n 1 a = ( 1) s a i (2 l ) i, i=0 0 a i < 2 l kaikille i = 0,..., n 1 ja a n 1 0, ja b ilmoittaa luvun merkin ja pituuden: b = s 2 l 1 + n (s {0, 1}). Luvut siis esitetään 2 l -kantaisessa järjestelmässä, ja b kertoo luvun pituuden ja merkin. Lukuja b ja a i kutsutaan tällä kurssilla numeroiksi vaikka ne itse asiassa ovat lukuja. Luvut a i kuitenkin vastaavat 2 l -kantaisen esityksen bittejä eli 1-numeroisia lukuja. Huomaa, että kokonaislukujen esittämiseen on olemassa myös muita tapoja, esim. binäärikoodatuilla desimaaleilla tai kakkosen komplementti esityksellä. Algoritmien kannalta ei ole olennaista, missä kannassa luvut esitetään. Vaikka algoritmit onkin yleensä tarkoitus toteuttaa tietokoneilla ja siten 2 l kantainen esitys olisi luonnollinen, voi olla helpompi ajatella normaalia 10 kantaista esitystä. Merkitään luvun a esitystä kantaluvun k suhteen a = (a n 1,..., a 1, a 0 ) k. Nyt siis a = n 1 i=0 a ik i, missä siis 0 a i < k. Määritellään, että luvun a pituus a l = n. (Kuten yllä todettiin, a:n esittämiseen tarvitaan itse asiassa n + 1 numeroa {0, 1,..., k 1}.) Näin ollen a l = log k a + 1. Algoritmien kompleksisuutta arvioitaessa riittää muistaa, että a l = O(log a). Alkeisoperaatioiksi on luonnollista määritellä 1-pituisilla luvuilla suoritettavat operaatiot: esim. yhteenlasku, kertolasku, vertailu ym. Näitä operaatioita kutsutaan usein bittioperaatioiksi riippumatta siitä, missä järjestelmässä luvut on annettu. Joskus algoritmien kompleksisuutta määrättäessä lasketaan aritmeettisten operaatioiden määrää. Tällä tarkoitetaan mielivaltaisen pitkien lukujen yhteen-, vähennys-, kerto- ja jakolaskujen määrää.
18 3.1 Kahden luvun vertailu Kahden luvun vertailu Kahden luvun vertailu on hyvin määritelty algoritminen probleema. Syötteenä saadaan luvut a ja b, ja tuloste on joko 0 tai 1 sen mukaan, onko a b vai a > b. Merkitään tätä probleemaa C(a, b):llä. C(a, b) on helppo ratkaista. Algoritmi 3.1. Algoritmi kahden luonnollisen luvun vertailemiseksi. syöte: luvut a, b tuloste: 0 jos a b, muuten 1 if a l < b l tai a l > b l then return 0 tai 1 else for i = a l 1 downto 0 do if a i < b i tai a i > b i then return 0 tai 1 return 0 (sillä a = b) Algoritmin kompleksisuutta arvioitaessa on siis laskettava vertailujen x < y määrä, missä x ja y ovat 1numeroisia lukuja. Jos a ja b ovat (korkeintaan) npituisia lukuja, niin selvästi 2n vertailua riittää aina. Näin ollen algoritmi toimii ajassa O(n). Pahimmassa tapauksessa (jos a ja b poikkeavat vain vähiten merkitsevässä numerossa) algoritmi myös vaatii mainitut 2n + 2 vertailua, joten se toimii ajassa Ω(n). Siis algoritmi toimii ajassa Θ(n). Yllä oleva algoritmi osoittaa, että probleema C(a, b) kuuluu luokkaan O(n). Mutta kuuluuko se luokkaan Θ(n); ts. vaatiiko jokainen sen ratkaiseva algoritmi ajan Ω(n)? Tämä on ilmeistä, sillä jos vertailuja tehdään vähemmän kuin n kappaletta (saati sitten vähemmän kuin O(n) kpl), jää väkisinkin jokin pari a i0, b i0 vertailematta. Tällaisella algoritmilla ei probleemaa voi ratkaista syötteellä, joissa a i = b i aina kun i i 0. Näin on perusteltu seuraava lause. Lause 3.1. Probleema C(a, b) on luokassa Θ(n). 3.2 Yhteen- ja vähennyslasku Olkoot a ja b einegatiivisia kokonaislukuja, ja olkoon niistä suuremman pituus n (käytetyssä kkantaisessa järjestelmässä). Merkitään A(a, b):llä probleemaa, jossa pitää laskea summa a + b, ja S(a, b):lla probleemaa, jossa pitää laskea erotus a b. Aivan kuten edellä vertailu-probleemassa on nytkin selvää, että probleemoja ei voida ratkaista alle lineaarisessa ajassa, joten ne ovat luokassa Ω(n).
19 3.3 Kertolasku 17 Toisaalta kumpikin probleema ratkeaa ajassa O(n) tutulla kouluaritmetiikalla. Yhteenlaskun suorittamiseen riittää 2n 1 alkeisoperaatiota, kun on otettu huomioon muistinumeroilla operointi. (Itse asiassa tietokoneen prosessorissa muistinumeroiden käsittely on yhdistetty alkeisyhteenlaskuun, jolloin voidaan sanoa, että n alkeisoperaatiota riittää.) Vähennyslaskun kompleksisuutta tarkasteltaessa muistinumerot aiheuttavat hiukan enemmän huolta, mutta siinäkin saadaan tarvittavien operaatioiden ylärajaksi cn, missä vakion c arvo riippuu alkeisvähennyslaskun tarkasta määritelmästä. Lause 3.2. Probleemat A(a, b) ja S(a, b) ovat luokassa Θ(n). 3.3 Kertolasku Merkitään kertolaskuprobleemaa M(a, b):llä. Oletetaan, että n-pituiset luvut a = (a n 1... a 1 a 0 ) k ja b = (b n 1... b 1 b 0 ) k ovat positiivisia. Koulussa opittu kertoalgoritmi toimii seuraavasti. Algoritmi 3.2. Koulualgoritmi kertolaskuun syöte: luvut a ja b tuloste: tulo ab t 0 for i = 0 to n 1 do x b i a t t + k i x return t Jokainen kertolasku b i a vaatii n alkeisoperaatiota (oletetaan, että muistinumeroilla operointi sisältyy alkeiskertolaskuun), ja summien t+k i x laskeminen vie korkeintaan 2n alkeisoperaatiota. Siis kullakin i:n arvolla suoritetaan maksimissaaan 3n operaatiota, joten algoritmin kompleksisuudelle saadaan yläraja 3n 2 = O(n 2 ). Taas on helppo nähdä, että kertolasku vaatii ainakin lineaarisen ajan, eli M(a, b) kuuluu luokkaan Ω(n). Edellinen algoritmi puolestaan osoitti, että M(a, b) kuuluu luokkaan O(n 2 ). Ongelman tarkkaa kompleksisuutta ei itse asiassa tiedetä, mutta myöhemmin näytetään, että koulualgoritmin antamaa ylärajaa voidaan parantaa. Todetaan vielä, että koulualgoritmin kompleksisuus on luokkaa O(mn), jos kerrottavista luvuista toinen on m ja toinen npituinen. Erityisesti, jos toinen luvuista on 1-numeroinen, on kompleksisuus luokkaa O(n).
20 3.4 Jakolasku Jakolasku Jakolaskuprobleemassa D(a, b) syötteenä on positiiviset kokonaisluvut a ja b ja tavoitteena on laskea pari (q, r), joka määräytyy yksikäsitteisesti ehdosta a = q b + r, missä 0 r < b. Oletetaan, että b on npituinen ja a (korkeintaan) 2npituinen luku. Tavanomainen koulussa opittu menetelmä johtaa jälleen kompleksisuutta O(n 2 ) olevaan algoritmiin: Jokainen q:n numero löytyy kokeilemalla (vakiomäärä kertolaskuja, joissa kerrottavat ovat 1- ja npituisia) ja vaatii O(n) operaatiota. Väite seuraa, koska q:n pituus on kertalukua O(n). Jos jakaja b on 1-pituinen luku, niin q:n numeroidenn etsimisessä lasketaankin kahden 1-numeroisen tuloja, jolloin jokainen numero löytyy vakioajassa. Siksi, aivan kuten kertolaskukin, ratkeaa jakolasku tässä tapauksessa ajassa O(n). Jakolaskun nopeuttaminen on hivenen hankalampaa kuin kertolaskun, ja sitä ei tällä kurssilla käsitellä. Voidaan kuitenkin osoittaa, että (tietyin lievin luonnollisin ehdoin) jakolasku voidaan suorittaa kertaluvultaan samassa ajassa kuin kertolasku. Polynomien aritmetiikkaa käsittelevässä luvussa näytetään, että polynomien jakolasku onnistuu samassa ajassa kuin polynomien kertolasku. 3.5 Binääriesityksen laskeminen Joissakin algoritmeissa on hyödyllistä tuntea luvun binääriesitys. Oletetaan taas, että a on k-kantaisessa järjestelmässä annettu npituinen luku. Probleemassa Bin(a) tehtävänä on laskea a:n binääriesitys; siis sellaiset bitit α i {0, 1}, että a = α i 2 i. Bin(a) voidaan ratkaista seuraavalla algoritmilla. Algoritmi 3.3. Algoritmi luvun binääriesityksen laskemiseksi. syöte: luku a = (a n 1 a 1 a 0 ) k tuloste: α = (α 0, α 1,... ) 2 : a = α i 2 i i 0 while a 0 do if a on pariton then α i 1 else α i 0 a a 2 i i + 1 return a = (α i 1 α 0 ) 2
21 3.6 Potenssi 19 Algoritmi laskee siis a:n bitit yhden kerrallaan vähiten merkitsevästä alkaen. Algoritmin kompleksisuus on helposti analysoitavissa. Kussakin silmukassa luvun a arvo pienenee ainakin puolella, joten kierrosten lukumäärä on korkeintaan log a +1 = O(n). Jokaisella kierroksella suoritetaan korkeintaan kaksi ajan O(n) vaativaa operaatiota, joten algoritmin kompleksisuus on kertalukua O(n 2 ). Lause 3.3. Probleema Bin(a) on luokassa O(n 2 ). Huomautettakoon vielä, että tietokoneissa luvut luonnollisesti esitetään binäärisesti, joten tällaista konversiota ei käytännössä yleensä tarvitse tehdä. 3.6 Potenssi Merkitään potenssinlaskuprobleemaa P a (e):llä. Tässä siis tehtävänä on laskea a e, missä kantaluku a ajatellaan kiinteäksi ja eksponentti e ajatellaan probleeman syötteeksi. Olkoon n eksponentin e pituus. Arvioidaan aluksi tarvittavien aritmeettisten operaatioiden lukumäärää; siis tässä tapauksessa tarvittavien kertolaskujen määrää, kun kerrottavat luvut saavat olla mielivaltaisen pitkiä. Triviaalissa menetelmässä a kerrotaan e 1 kertaa itsellään tarvitaan e 1 = 2 O(n) kertolaskua. Kompleksisuus on siis eksponentiaalinen, vaikka tarkastellaan pelkästään aritmeettisia operaatioita. Suuria potensseja ei tällä tavalla voi laskea. Mutta on olemassa paljon tehokkaampikin metodi; ns. peräkkäisten neliöiden menetelmä. Algoritmi 3.4. Peräkkäisten neliöiden menetelmä potenssilaskuun. syöte: kantaluku a, eksponentti e = (e n 1 e 1 e 0 ) 2 tuloste: a e x a, z 1 for i = 0 to n 1 do if e i = 1 then z zx x x 2 return z Algoritmin oikea toiminta seuraa alla olevasta laskusta: a e = a e 0+e e n 1 2 n 1 = a e0 (a 2 ) e1 (a 2n 1 ) c n 1. Laskussa (ja yllä olevassa algoritmissa) tarvitaan n neliöintiä ja korkeintaan n tavallista kertolaskua, siis O(n) aritmeettista operaatiota. (Kertaluku ei muutu miksikään, vaikka e:n binääriesitys pitäisi myös laskea.) On myös ilmeistä, että O(n) aritmeettista operaatiota myös aina tarvitaan.
22 3.7 Suurin yhteinen tekijä 20 Lause 3.4. Probleema P a (e) ratkeaa lineaarisessa määrässä aritmeettisia operaatioita. On huomattava, että yllä laskettiin aritmeettisia operaatioita. Jos lasketaan 1numeroisilla luvuilla tehtäviä operaatiota (bittioperaatioita), kompleksisuus muuttuu eksponentiaaliseksi. Näin käy välttämättä kaikilla ongelman ratkaisevilla algoritmeilla. Itse asiassa pelkästään vastauksen tulostaminen vie eksponentiaalisen ajan, sillä a e l e a l 2 n a l = 2 O(n). Huomautus 3.1. Peräkkäisten neliöiden menetelmää voidaan soveltaa myös tulon a a... a laskemiseen, missä on mikä tahansa assosiatiivinen binäärioperaatio. Menetelmä soveltuu siis vaikka neliömatriisien potenssin laskemiseen. 3.7 Suurin yhteinen tekijä Probleemassa gcd(a, b) tehtävänä on määrätä lukujen a ja b suurin yhteinen tekijä syt(a, b), missä a b 0. Olkoon n luvun a pituus. Ongelma ratkeaa jo antiikin ajoilta tunnetulla Eukleideen algoritmilla. Algoritmi perustuu yhtälöön syt(a, b) = syt(b, r), missä a = qb + r ja 0 r < b. Olkoon Div jokin jakoalgoritmi: yllä olevin merkinnöin Div(a, b) = (q, r). Algoritmi 3.5. Eukleideen algoritmi (rekursiivinen versio) syöte: luvut a, b, a b > 0 tuloste: syt(a, b) kutsu: Eucl(a, b) (q, r) Div(a, b) if r = 0 then return b else return Eucl(b, r) Eukleideen algoritmi laskee siis suurimman yhteisen tekijän suorittamalla joukon jakolaskuja, joista kukin voidaan tehdä ajassa O(n 2 ). Koko algoritmin kompleksisuuden määräämiseksi pitäisi saada arvio jakolaskujen määrälle; olkoon se k + 1. Merkitään algoritmin aikana laskettuja jakojäännöksiä järjestyksessä r k, r k 1,..., r 0, joten esimerkiksi r k = a mod b ja r 0 = 0. Näytetään, että luvut
23 3.7 Suurin yhteinen tekijä 21 r i toteuttavat epäyhtälön r i F i kun i = 0,..., k, missä F i on i:s Fibonaccin luku (F 0 = 0, F 1 = 1, F i+2 = F i+1 + F i ). Tämä onnistuu kätevästi induktiolla. Asia on selvä, kun i = 0 ja i = 1. Toisaalta, koska r i 1 saadaan algoritmilla jakolaskulla (q, r i 1 ) Div(r i+1, r i ), joten r i+1 = qr i + r i 1 r i + r i 1 i.o. F i + F i 1 = F i+1, mikä todistaa induktioaskelen. Voidaan osoittaa, että Fibonaccin luvut toteuttavat epäyhtälön F i A α i sopivasti valituilla vakioilla A > 0 ja α > 1. On siis saatu a > r k F k A α k. Ottamalla logaritmit molemmin puolin tästä seuraa k < n log A = O(n), log α koska n log a. Siispä seuraava lause on todistettu. Lause 3.5. Probleema gcd(a, b) kuuluu luokkaan O(n 3 ). Huomautettakoon, että yllä oleva Eukleideen algoritmin kompleksisuuden analysointi on historiallisesti merkittävä. Sitä pidetään ensimmäisenä epätriviaalina algoritmin analysointina (Lame, 1845). Mainittakoon myös, että saatu yläraja tarvittavien jakolaskujen määrälle on siinä mielessä tarkka, että joissakin tapauksissa todella tarvitaan O(n) jakolaskua. Näin käy esimerkiksi laskettaessa kahden peräkkäisen Fibonaccin luvun suurinta yhteistä tekijää. Huomaa, etä arvioimme jakolaskun kompleksisuudeksi O(n 2 ), joten käyttämällä koulualgoritmia nopeampaa jakoalgoritmia saadaan Eukleideen algoritmia nopeutettua. Yksinkertaisuudestaan huolimatta Eukleideen algoritmi on varsin hyödyllinen. Esimerkiksi käänteisalkion laskeminen jäännösluokkarenkaassa onnistuu mukavasti ns. laajennetulla Eukleideen algoritmilla, kuten myöhemmin nähdään. Suurimman yhteisen tekijän laskemiselle tunnetaan muitakin algoritmeja. Ne perustuvat Eukleideen algoritmin ns. matriisiversioon, joka esitettään monisteen seuraavassa luvussa. Matriisiversiossa keskeisessä osassa on kertolaskualgoritmin valinta. Valitsemalla asymptoottisesti tehokkain kertolaskualgoritmi saadaan suurin yhteinen tekijä laskettu alle kuutiollisessa ajassa. Esimerkiksi ns. Stehlé-Zimmermann algoritmi ja Schönhagen algoritmi toimivat ajassa O(log nm(n)), missä M(n) on kertolaskualgoritmin kompleksisuus. Esimerkki 3.1. Lasketaan lukujen 1175 ja 359 suurin yhteinen tekijä Eukleideen algoritmilla.
24 3.8 Neliöjuuri Neliöjuuri Tehokkaimmat menetelmät neliöjuuren laskemiseen ovat likimääräisalgoritmeja (esim. numeerisesta analyysistä tuttu Newtonin menetelmä). Nämä metodit eivät ole algoritmisesti selkeitä, sillä ne vaativat mm. virhetarkastelun. Ensimmäinen tunnettu likimääräisalgoritmi luvun a likiarvon laskemiseksi tunnetaan nimellä Babylonialaisten metodi tai Heronin metodi. Se perustuu nimenomaan Newtonin metodiin, joskin algoritmi löydettiin jo ennen Newtonin metodia. Voidaan osoittaa, että oikeiden numeroiden lukumäärä likiarvossa lähes tuplaantuu jokaisella iteraatiokierroksella. Babylonialaisten metodin idea voidaan esittää lyhyesti seuraavasti: Algoritmi 3.6. Babylonialaisten metodi luvun a likiarvolle Aseta luvuksi x 0 jokin luku for n = 0 to( k do ) x n x n + a x n return x k+1 Tietysti on hyvä valita luku x 0 mahdollisimman läheltä a:ta. Ongelmaa voidaan kuitenkin tarkastella puhtaasti algoritmisestikin. Merkitään Sqrt(a):lla probleemaa, jossa syöte a on npituinen kokonaisluku ja tehtävänä on laskea a. Lause 3.6. Probleema Sqrt(a) kuuluu luokkaan O(n 3 ). Todistus. Perustellaan lause kuvailemalla vaaditussa ajassa toimiva ratkaisualgoritmi. Merkitään a = m 1 i=0 a i (k 2 ) i ja b = m 1 i=0 b i k i, missä b = a, m = n 2, 0 a i < k 2 ja 0 b i < k. Voidaan osoittaa (induktiolla), että m 2 (b m 1 b m 2 b 0 ) 2 k = b2 m 1k 2(m 1) + k 2i (2k(b m 1 b i+1 ) k + b i )b i. (1) Nyt huomataan, että i=0 b 2 m 1 a m 1 < (b m 1 + 1) 2,
25 3.8 Neliöjuuri 23 joten b m 1 saadaan selville kokeilemalla maksimissaan kaikki k vaihtoehtoa. Vastaavasti voidaan osoittaa, että kaikilla i:n arvoilla ((b m 1 b m i ) k ) 2 (a m 1 a m i ) k 2 ((b m 1 b m i ) k + 1) 2. Nyt luvut b m 1,..., b m i+1 tunnetaan, joten taas b m i voidaan selvittää etsimällä se arvo, joka toteuttaa epäyhtälöt. Laskun kompleksisuus on nyt T (n) = m i=1 T i(n), missä T i on luvun b m i laskemiseen käytettävä aika. Tällöin lasketaan muotoa (b m 1 b m i ) 2 olevia neliöitä, siis ipituisten lukujen tuloja. Näin ollen T i = O(i 2 ), ja saadaan m T (n) = O(i 2 ) = O(m 3 ). Koska m = O(n), väite seuraa. i=1 Algoritmia voidaan nopeuttaa, sillä neliöjuuren numero b m i voidaan laskea ajassa O(i). Nimittäin, ((b m 1 b m i ) k ) 2 = (k(b m 1 b m i+1 ) k + b m i ) 2 = k 2 (b m 1 b m i+1 ) 2 k + 2k(b m 1 b m i+1 ) k b m i + b 2 m i. (2) Koska (b m 1 b m i+1 ) 2 k on laskettu edellisellä kierroksella, saadaan (b m 1 b m i ) 2 k nyt laskettua laskemalla kaksi i-pituisen luvun ja 1-pituisen luvun tuloa, yksi 1-pituisten tulo sekä i-pituisten lukujen yhteenlasku. Tästä seuraa kompleksisuus O(i) numeron b m i laskemiselle. Lause 3.7. Sqrt(a) kuuluu jopa luokkaan O(n 2 ). Itse asiassa, kaavasta (2) ja todistuksen epäyhtälöstä seuraa, että b m i on suurin numero, jolle 2k(b m 1 b m i+1 ) k b m i +b 2 m i (a m 1 a m i ) k 2 ((b m 1 b m i+1 ) k ) 2 k 2. Nyt pitämällä kirjaa erotuksesta (a m 1 a m i ) k 2 ((b m 1 b m i+1 ) k ) 2 k 2 voidaan neliöjuuri laske kätevästi neliöjuurikulmassa Esimerkki 3.2. Lasketaan lukujen 1156 ja neliöjuuret. Algoritmia voidaan jatkaa senkin jälkeen, kun b 0 on laskettu. Silloin jokaisella kierroksella saadaan yksi desimaali a:n likiarvosta lisää. Näin ollen a:n k ensimmäistä desimaalia saadaan selville ajassa O((n + k)) 2. Huomaa, että algoritmi laskee desimaalit oikeina, ei pyöristettyinä.
26 24 4 Aritmetiikkaa renkaassa Z m Usein esimerkiksi koodausteoriassa ja kryptograassa käytettävä algebrallinen struktuuri on jäännösluokkarengas Z m. Tämän renkaan alkiot esitetään yleisesti kokonaislukuina i, missä 0 i < m. Näin ollen aina n = a l log m 1. Jatkossa merkintä a mod m tarkoittaa nimenomaan sitä lukua joukosta {0, 1,..., m 1}, jonka kanssa a on kongruentti modulo m. 4.1 Yhteen-, kerto- ja vähennyslasku Kuten tiedetään, yhteen- ja kertolasku renkaassa Z m määritellään kokonaislukujen vastaavan operaation avulla. Esimerkiksi summa (vast. tulo) saadaan laskemalla kokonaislukujen summa (vast. tulo) ja redusoimalla vastaus välille {0, 1,..., m 1}. Merkitään modulaarisen yhteen-, kerto- ja vähennyslaskun probleemia ModA(a, b):lla, ModM(a, b):lla ja ModS(a, b):lla. Tarkastellaan ensiksi summan laskemista. Jos alunperin 0 a, b < m, niin 0 a + b < 2m, joten luvun a + b Z m esitys on aina joko a + b tai a + b m. Näin ollen ongelma ratkeaa kokonaislukujen yhteenlaskulla, vertailulla ja (tarvittaessa) vähennyslaskulla. Kompleksisuus on tällöin lineaarinen, eli kertalukua O(n). Tulon laskemisessa redusoitava luku voi olla paljon suurempi, sillä 0 a, b < m = 0 ab < m 2. Nytkin voitaisiin tulosta vähentää luku m niin monta kertaa, että tulos asettuu halutulle välille, mutta näin saataisiin aivan liian hidas algoritmi. Itse asiassa kompleksisuus olisi eksponentiaalinen, koska pahimmassa tapauksessa vähennyslasku tulisi laskettavaksi m 1 = 2 log m 1 = 2 n kertaa. Tehokkaampi vaihtoehto on käyttää jakoalgoritmia: jos ab = qm + r, niin ab mod m = r. Tulon laskeminen siis palautuu kahden npituisen kokonaisluvun tulon laskemiseen ja 2npituisen luvun jakamiseen npituisella luvulla. Koulualgoritmeja käyttäen näin saadaan neliöllinen algoritmi, kompleksisuus on siis kertalukua O(n 2 ). Vähennyslasku voidaan hoitaa samaan tyyliin kuin yhteenlasku. Tai jos negatiivisia lukuja ei ole mahdollista esittää, voidaan erotus laskea kaavasta a b = a+(m b) mod m. Joka tapauksessa vähennyslaskun kompleksisuus on kertalukua O(n). Kaikki käsitellyt probleemat vaativat triviaalisti ajan Ω(n). Modulaarinen kertolasku saatiin jo koulualgoritmeilla luokkaan O(n 2 ), ja käyttämällä nopeampia kokonaislukujen kerto- ja jakoalgoritmeja voitaisiin kompleksisuutta vastaavasti pudottaa. Käytännön tilanteissa moduli m on kuitenkin yleensä niin pieni, että koulualgoritmit ovat riittävän tehokkaita. Lause 4.1. Probleemat ModA(a, b) ja ModS(a, b) kuuluvat luokkaan Θ(n), ja probleema ModM(a, b) kuuluu luokkaan O(n 2 ).
27 4.2 Käänteisalkio ja jakolasku Käänteisalkio ja jakolasku Jakolasku a/b mod m renkaassa Z m on luonnollisesti määritelty vain silloin, kun alkiolla b on olemassa käänteisalkio b 1 renkaassa Z m. Käänteisalkio b 1 toteutaa siis ehdon bb 1 1 (mod m) ja jakolasku tulee oikeastaan määriteltyä tulona ab 1 (mod m). Tiedetään, että käänteisalkio on olemassa tarkalleen silloin, kun syt(b, m) = 1, ts. b Z m = {x 1 x < m, syt(x, m) = 1}. Käänteisalkio voidaan laskea soveltamalla Eukleideen algoritmin laskuja takaperin. Jos syt(b, m) = 1, löydetään sellaiset luvut u ja v, että ub + vm = 1. Nyt siis b 1 u mod m. Sen lisäksi, että (paperilla laskiessa) Eukleideen algoritmin laskujen soveltaminen takaperin on varsin hankalaa, vaatii se tietokoneellakin implementoiden paljon muistia. Seuraava algoritmi on kätevämpi sekä paperilla laskiessa että ohjelmoitaessa. Olkoon taas Div jokin jakoalgoritmi. Algoritmi 4.1. Eukleideen algoritmi käänteisalkion laskemiseen Z m:ssä. syöte: luku a Z m, moduli m tuloste: a 1 mod m A = α β x 1 0 a, B q 1 γ δ y 0 1 m 1 0 while x 1 do (q, r) Div(y, x) A BA mod m return α Voidaan osoittaa, että algoritmin jokaisen while silmukan jälkeen α β a = x, γ δ m y ja lisäksi x on tarkalleen sama kuin Eukleideen algoritmin 3.5 muuttuja r. Kun x = 1, saadaan siis αa + βm = 1, mistä seuraa, että αa 1 (mod m), joten a 1 α (mod m). Algoritmin kompleksisuus on samaa kertalukua kuin Eukleideen algoritmin perusversiossa. Kierroksia tarvitaan yhtä monta (O(n)), ja kukin kierros
28 4.3 Modulaarinen potenssilasku 26 vaatii nytkin O(n 2 ) operaatiota, jos kertolaskussa käytetään koulualgoritmia. Käänteisalkio modulo m löytyy siis kuutiollisessa ajassa O(n 3 ). Aivan kuten Eukleideen algortimin rekursiivista muotoa, voidaan tätäkin algoritmia nopeuttaa käyttämällä nopeampaa kertolaskualgoritmia. Esimerkki 4.1. Lasketaan 28 1 mod Siis = 1 ja näin ollen (mod 75) Lineaarinen kongruenssiyhtälö Tarkastellaan vielä lineaarista kongruenssiyhtälöä ax b (mod m), 0 a, b < m. Tiedetään, että tällä yhtälöllä on ratkaisu silloin ja vain silloin, kun d = syt(a, m) jakaa luvun b. Tällöin kongruenssilla a d x b d (mod m d ) on yksikäsitteinen ratkaisu x 0 = ( a d ) 1 b d modulo m d. Alkuperäisen kongruenssin kaikki ratkaisut ovat nyt muotoa x x 0 + i m d (mod m), missä i = 0, 1,..., d 1. Yllä olevan perusteella lineaarisen kongruenssiyhtälön ratkaiseminen onnistuu ajassa O(n 3 ), missä n on modulin m pituus. 4.3 Modulaarinen potenssilasku Aiemmin esitettiin peräkkäisten neliöiden menetelmä kokonaisluvun a e laskemiseen. Todettiin, että aritmeettisia operaatioita tarvitaan Θ(n) kappaletta (n = e l ). Kokonaislukujen tapauksessa aritmeettisten operaatioiden määrä on kuitenkin huono mittari probleeman kompleksisuudelle, sillä bittioperaatioita tarvitaan eksponentiaalinen määrä. Ongelmakasi muodostui se, että käsiteltävät luvut (kuten myös lopullinen vastaus) kasvoivat eksponentiaalisen pitkiksi. Laskettaessa alkiota a e mod m ei lukujen pituus kertolaskuissa kasva rajatta. Modulaarinen potenssi voidaan laskea käyttäen samaa peräkkäisten neliöiden menetelmää, mikä esitettiin aiemmin. Kertolaskut ab korvataan vain kertolaskuilla ab mod m, mikä tehdään suorittamalla ensin tavallinen kertolasku ja sen jälkeen redusoimalla tulos välille [0, m 1]. Tavallisen kertolaskun ja modulaarisen kertolaskun asymptoottiset kompleksisuudet ovat samat; O(n 2 ) (n = a l ), jos käytetään koulualgoritmeja. Näin ollen a e (mod m) voidaan laskea (ainakin) ajassa O(n 3 ).
29 4.3 Modulaarinen potenssilasku 27 Alla esitetään peräkkäisten neliöiden menetelmä hieman modioituna. Oletetaan, että 0 < a, e < m. Jos näin ei ole, pitäisi aluksi a redusoida modulo m ja e redusoida modulo ϕ(m), missä ϕ(m) = Z m on Eulerin ϕ- funktio. Algoritmi 4.2. Algoritmi modulaariseen potenssilaskuun. syöte: kantaluku a, moduli m ja eksponentti e = (e n 1 c 1 c 0 ) 2 tuloste: a e mod m z 1 for i = n 1 downto 0 do z z 2 mod m if e i = 1 then z za mod m return z Yllä oleva osoittaa, että modulaarinen potenssi (modulaarinen eksponenttifunktio) voidaan laskea polynomiajassa, siis tehokkaasti. Sen sijaan tavallisen eksponenttifunktion laskeminen vaatii aina eksponentiaalisen ajan. Esimerkki 4.2. Lasketaan (mod 789). Eksponentin e = 456 binääriesitys on 456 = ( ) 2, joten algoritmissa n = 9. Alla on taulukoitu muuttujan z arvot kunkin for silmukan jälkeen. i e i z Esimerkiksi, kun i = 7, lasketaan ensin mod 789 = 138, ja koska e 7 = 1 lasketaan vielä z = mod 789 = 405. Kierroksella i = 4 on e 4 = 0, jolloin z = mod 789 = 372. Lopuksi saadaan tulos (mod 789). Mainittakoon, että funktion a e mod m laskemisella on kryptograassa erityisen tärkeä sovellus. Tunnetuin ja käytetyin ns. julkisen avaimen salausjärjestelmä RSA perustuu juuri tähän funktioon. Käytännön syistä salaamisen on oltava tehokasta, ja RSA:ssa se tehdään juuri laskemalla modulaarinen eksponenttifunktio. Jotta systeemi olisi turvallinen, pitää salauksen käänteisfunktion a e mod m a olla vaikea laskea. Tälle ongelmalle ei tunneta polynomiaikaista algoritmia, jos moduli m on sopivaa muotoa (kahden alkuluvun tulo). Valitsemalla siis moduli m kahden riittävän suuren alkuluvun tuloksi, ei näin saatavaa salaussysteemiä voi käytännössä murtaa.
30 4.3 Modulaarinen potenssilasku RSA-salakirjoitusmenetelmä Tässä pykälässä käsitellään modernia RSA-salakirjoitusjärjestelmää. Se on julkinen seuraavassa mielessä: henkilö X julkistaa (esim. sanomalehdessä), miten hänelle tulevat viestit tulee kryptata, ts. kirjoittaa salakirjoitettuun muotoon. Tällöin kuka tahansa voi suorittaa kryptauksen ja lähettää salaisia viestejä henkilölle X, mutta siitä huolimatta, että kryptausmenetelmä on tiedossa, vain henkilö X pystyy dekryptaamaan, ts. purkamaan salakirjoituksen. Jos a ja b ovat positiivisia kokonaislukuja, joille syt(a, b) = 1, niin lauseen 8.11 avulla löydetään sellaiset kokonaisluvut u ja v, että ua + vb = 1. Koska myös (u+xb)a+(v xa)b = 1 kaikilla kokonaisluvuilla x, voidaan haluttaessa olettaa, että u on positiivinen ja v negatiivinen. Henkilö X valitsee kaksi suurta (esim. 300-numeroista) alkulukua p ja q ja muodostaa tulon n = pq. Edelleen hän valitsee jonkin positiivisen kokonaisluvun e 1, jonka suurin yhteinen tekijä luvun (p 1)(q 1) kanssa on 1, ja etsii (Eukleideen algoritmilla) sellaiset kokonaisluvut d > 0 ja d < 0, joille 1 = de + d (p 1)(q 1). Merkitään d = d > 0. Tällöin 1 = de d (p 1)(q 1). Tämän jälkeen henkilö X julkistaa luvut n ja e, mutta pitää luvut p, q ja d omana tietonaan. Nyt kuka tahansa voi lähettää salaisen viestin henkilölle X seuraavalla tavalla. Ensiksi viesti koodataan jollakin ennalta sovitulla tavalla kokonaislukujonoksi M 1, M 2,..., missä kullakin indeksin i arvolla 0 M i < n. Jos n on suunnilleen 600- numeroinen, tarkoittaa tämä, että binäärimuotoisesta viestistä otetaan suunnilleen 2000 bitin pätkä kerrallaan, joka aina muodostaa yhden kokonaisluvun M i. Viestin lähettäjä suorittaa nyt kryptauksen suorittamalla laskun M e i m i (mod n), ts. korottaa luvun M i kryptauseksponentin e ilmoittamaan potenssiin ja laskee saadun luvun jäännöksen modulo n. Salakirjoitettu viesti, ns. kryptoteksti on jono m 1, m 2,.... Lause 4.2. m d i M i (mod n).
31 4.3 Modulaarinen potenssilasku 29 Tämän lauseen nojalla henkilö X joka ainoana tuntee luvun d voi suorittaa dekryptauksen eli selvittää, mikä oli alkuperäinen selväkielinen viesti. Edellisen lauseen todistamiseksi tarvitaan seuraava aputulos. Lause 4.3 (Fermat'n pieni lause). Jos p on alkuluku ja a Z ei ole jaollinen luvulla p, niin a p 1 1 (mod p). Lauseen 4.2 todistus. Jos p ei jaa lukua M i, niin Fermat'n pienen lauseen nojalla m d i M ed i = M 1+d (p 1)(q 1) i Jos taas p M i, joten myös tällöin = (M p 1 i ) d (q 1) M i M i (mod p). m d i M ed i M i (mod p). Samoin tietysti m d i M i (mod q). Koska p ja q ovat eri alkulukuja, ja m d i M i on jaollinen sekä luvulla p että q, on se jaollinen luvulla pq. Näin m d i M i (mod pq). RSA-kryptosysteemin pystyy periaatteessa murtamaan yksinkertaisella tavalla: etsitään luvun n tekijät p ja q ja julkisesta avaimesta e lasketaan d ja d. Tämän jälkeen kaikki salatut viestit voidaan lukea. Kyseinen murto lopahtaa siihen seikkaan, että luvun n tekijöihinjaolle (ei vaikka tiedettäisiin, että tekijöitä on kaksi) ei ole olemassa nopeaa algoritmia. Ts. tekijöihinjako parhaillakin tunnetuilla algoritmeilla on niin työlästä, että kun X valitsee riittävän suuret luvut p ja q, niin se ei onnistu missään kohtuullisessa ajassa. RSA perustuu siihen, että modulaarinen eksponenttifunktio on ns. yhdensuunnan (one-way function) funktio. Tämä tarkoittaa sitä, että itse funktio on nopea laskea, mutta sen käänteisfunktio on erittäin hidas laskea ilman lisätietoa (trapdoor), jonka avulla käänteisfunktiokin tulee nopeaksi laskea. Esimerkki 4.3. Oletetaan, että Bob valitsee alkuluvut p = 5 ja q = 11. Hän laskee, että n = 55 ja (p 1)(q 1) = 40. Hän valitsee e = 7, ja tarkistaa Eukleideen algoritmilla, että syt(e, 40) = 1, ja laskee edelleen luvun d, jolle ed 1 (mod 40). Hän saa, että d (mod 40) = 23. Bobin julkinen avain on (n, e) = (55, 7) jonka hän kertoo kaikille ja pitää omana tietonaan salaisen avaimensa (n, d) = (55, 23). Alice haluaa lähettää Bobille salaisen viestin x = 17. Hän laskee Bobin julkisella avaimella E(x) = (mod 55), ja lähettää Bobille kryptotekstin y = 8. Bob, saatuaan vietin y, käyttää salaista avaintaan ja laskee: x = D(y) = (mod 55).
32 4.3 Modulaarinen potenssilasku 30 On selvää, että tässä esimerkissä valitut alkuluvut 5 ja 11 ovat käytännössä liian pieniä. Esimerkki 4.4. Oletetaan, että Bobin julkinen avain on (n, e) = (2773, 17). Alice haluaa lähettää Bobille viestin Go to Rivendell. Aluksi hänen pitää koodata teksti luvuiksi. Hän käyttää yksinkertaista tapaa, joka näkyy alla olevasta taulukosta A B C D E F G H I J K L M N O P Q R S T U V W X Y Z Luku 2773 on niin suuri, että Alice koodaa kirjaimet kahden pituisina pätkinä. Siis GO TO RI VE ND EL LX Nyt kryptaus tapahtuu laskemalla näiden lukujen 17. potenssit modulo 2773: x x x x x x 17 = x x Alice lähettää siis Bobille viestin (1412, 2507, 1810, 1565, 862, 557, 2688).
33 31 5 Algoritmien suunnittelusta Algoritmien suunnittelemiseksi voidaan esittää monia menetelmiä. Aritmeettisten ja lukuteoreettisten probleemien kannalta ehkä hyödyllisin metodi on hajoitajahallitse -menetelmä. Myös dynaaminen suunnittelu soveltuu joihinkin tilanteisiin. Algoritmien suunnittelusta puhuttaessa useimmiten mainitaan myös ahneet algoritmit. Ne eivät kuitenkaan sovellu kovin hyvin matemaattisten funktioiden laskemiseen, mistä syystä tässä monisteessa niitä ei käsitellä. 5.1 Hajoita-ja-hallitse -menetelmä Hajoita-ja-hallitse -algoritmit koostuvat kolmesta vaiheesta. (i) Hajoita: Ratkaistava ongelma hajoitetaan joukkoon aliongelmia. (ii) Hallitse: Aliongelmat ratkaistaan rekursiivisesti; paitsi jos ne ovat riittävän pieniä, jolloin ne ratkaistaan jollain suoraviivaisella menetelmällä. (iii) Yhdistä: Muodostetaan aliongelmien ratkaisuista alkuperäisen ongelman ratkaisu. Menetelmän kolme vaihetta käyvät hyvin ilmi seuraavasta ei-matemaattisesta algoritmista. Esimerkki 5.1. Annetun listan lajittelu on tietojenkäsittelyssä tärkeä ongelma. Triviaalit algoritmit suoriutuvat lajittelusta ajassa Θ(n 2 ), missä n on listan alkioiden lukumäärä. Ns. limityslajittelu on hajoitajahallitse -algoritmi, joka suoriutuu tehtävästä nopeammin. (i) Hajoita lajiteltava lista kahteen puolta pienempää alilistaan. (ii) Lajittele alilistat rekursiivisesti; siis käyttäen limityslajittelua. (iii) Limitä valmiiksi lajitellut alilistat keskenään, jolloin tuloksena on alkuperäinen lista lajiteltuna. On selvää, että limitysvaihe voidaan suorittaa ajassa Θ(n), joten algoritmin kompleksisuus toteuttaa rekursioyhtälön. T (n) = 2T ( n 2 ) + Θ(n). T (n) voidaan ratkaista tästä yhtälöstä ja tässä tapapuksessa T (n) = Θ(n log n).
34 5.2 Rekursioyhtälöiden ratkaisemisesta Rekursioyhtälöiden ratkaisemisesta Seuraavaksi esitetään ja todistetaan menetelmä, jolla voidaan rutiininomaisesti ratkaista muotoa T (n) = at (n/b) + f(n) (3) olevat rekursioyhtälöt, missä a 1 ja b > 1. Tarkastellaan hajoitajahallitse -algoritmia, missä n-kokoinen ongelma hajoitetaan a:han kokoa olevaan n/b aliongelmaan. Jos jako aliongelmiin ja aliongelmien ratkaisujen yhdistäminen alkuperäisen ongelman ratkaisuksi vaatii ajan f(n), niin päädytään juuri yllä rekursioyhtälöön (3). Lause 5.1. Olkoot a 1 ja b > 1 vakioita, ja oletetaan, että T (n) toteuttaa rekursioyhtälön T (n) = at ( n) + f(n), b missä n b voi tarkoittaa kumpaa tahansa luvuista n b tai n b. Silloin 1. T (n) = Θ(n log b a ), jos f(n) = O(n (log b a) ɛ ) jollakin vakiolla ɛ > T (n) = Θ(log n n log b a ), jos f(n) = Θ(n log b a ). 3. T (n) = Θ(f(n)), jos f(n) = Ω(n (log b a)+ɛ ) jollakin vakiolla ɛ > 0, ja jos jostakin rajasta n n 0 lähtien af( n b ) cf(n) jollakin vakiolla c < 1. Lauseessa siis verrataan funktioita f(n) ja n log b a toisiinsa ja ratkaisuna saadaan, että T (n) on kertaluvultaan samaa luokkaa kuin suurempi näistä. Poikkeuksena on tilanne, jossa vertailtavat funktiot ovat samaa kertalukua, jolloin ratkaisuun tulee ylimääräinen log n -tekijä. Todistus. Todistetaan lause tapauksessa, kun n = b i jollakin kokonaisluvulla i. Muissa tapauksissa lattia- ja kattosulkeiden tuomat hankaluudet voidaan käsitellä samaan tapaan kuin ehdollisen kompleksisuuden lemmassa 2.1. Jaetaan ensin rekursioyhtälön ratkaisu kahteen osaan: T (n) = at (n/b) + f(n) = a 2 T (n/b 2 ) + af(n/b) + f(n) =... i 1 = a i T (1) + a j f(n/b j ) j=0 Ensimmäinen termi a i T (1) = a log b n T (1) = Θ(n log b a ) vastaa hajoitaja hallitse -algoritmissa kaikkien 1-kokoisten ongelmien ratkaisuun vaadittavaa aikaa, kun taas toinen termi (merk. g(n)) vastaa aliongelmiin jakamiseen ja ratkaisujen yhdistämiseen kuluvaa aikaa. Tarkastellaan g(n):n suuruutta eri tapauksissa.
35 5.2 Rekursioyhtälöiden ratkaisemisesta 33 Olkoon aluksi f(n) = O(n (log b a) ɛ ), joten f(n/b j ) = O((n/b j ) (log b a) ɛ ). Sijoittamalla tämä g(n):n lausekkeeseen saadaan i 1 g(n) = O a j( n ) logb a ɛ b j. j=0 Muokkaamalla näin saatua ylärajaa saadaan i 1 a j( n ) logb i 1 ( a ɛ b j = n log b ab a ɛ ɛ j=0 j=0 b log b a ) j i 1 ( = n log b a ɛ (b ɛ ) j = n log b b a ɛ ɛ log n ) b 1 b ɛ 1 j=0 ( = n log b n a ɛ ɛ ) 1 b ɛ. 1 Koska b ja ɛ ovat vakioita, on saatu lauseke kertalukua n log b a ɛ O(n ɛ ). Siis g(n) = O(n log b a ), joten lauseen kohta 1 on todistettu. Oletetaan seuraavaksi, että f(n) = Ω(n (log b a)+ɛ ). Koska kaikilla riittävän suurilla n:n arvoilla af(n/b) cf(n), niin induktiolla saadaan, että a j f(n/b j ) c j f(n). Nyt funktiolle g(n) saadaan yläraja g(n) = f(n) + af(n/b) + a 2 f(n/b 2 ) a i 1 f(n/b i 1 ) i 1 f(n) c j f(n) 1 c, j=0 missä viimeinen arvio saadaan geometrisen summan laskukaavasta (c < 1). Siispä g(n) = O(f(n)). Triviaalisti myös g(n) = Ω(f(n)), joten T (n) = Θ(g(n)) = Θ(f(n)). Tämä todistaa lauseen kohdan 3. Lauseen kohdassa 2 on f(n) = Θ(n log b a ). Nyt kaikilla j:n arvoilla on ( a j n ) logb a ( = n log b a a ) j = n log a b b j b log b a. Näin ollen T (n) = Θ(n log b a ) + g(n) = Θ(log n n log b a ). Esimerkki 5.2. Tarkastellaan rekursioyhtälöä T (n) = 9T (n/3) + f(n), joka on edellisen lauseen vaatimaa muotoa. Tehtävänä on siis verrata funktioita f(n) ja n log 3 9 = n 2. Nyt siis esimerkiksi f(n) = n T (n) = Θ(n 2 ); f(n) = n 2 T (n) = Θ(n 2 log n); f(n) = n 3 T (n) = Θ(n 3 ). Tapauksessa f(n) = n 3 pitää vielä huomata, että 9f(n/3) = 1 3 n3, joten lausetta voidaan todella soveltaa.
36 5.3 Karatsuba-kertolasku Karatsuba-kertolasku Tämän monisteen ensimmäisessä luvussa esitettiin tyypillinen hajoita-jahallitse algoritmi kokonaislukujen tulon laskemiseen, jossa kahden n-pituisen luvun tulo saatiin laskemalla neljä n/2-pituisten lukujen tuloa ynnä joitakin summauksia. Saadaan rekursioyhtälö T (n) = 4 T (n/2) + Θ(n). Lauseen 5.1 mukaan ratkaisuksi saadaan T (n) = Θ(n 2 ), joten algoritmin kompleksisuus on tarkalleen samaa kertalukua kuin koulualgoritmilla. Tätä menetelmää voidaan kuitenkin parantaa. Olkoot a ja b kaksi npituista kokonaislukua kkantaisessa järjestelmässä (k:n arvolla ei ole merkitystä). Oletetaan myös yksinkertaisuuden vuoksi, että n on kakkosen potenssi. Merkitään Nyt voidaan kirjoittaa a = a 1 k n 2 + a0 ja b = b 1 k n 2 + b0. missä ab = (a 1 k n 2 + a0 ) (b 1 k n 2 + b0 ) = α 1 k n + (α 3 α 2 α 1 )k n 2 + α2, α 1 = a 1 b 1, α 2 = a 0 b 0, ja α 3 = (a 1 + a 0 )(b 1 + b 0 ). Näin ollen kahden npituisen luvun tulon laskeminen palautuu (i) kahteen n 2 pituisten lukujen tulon laskemiseen; (ii) yhteen n pituisten lukujen tulon laskemiseen; ja (iii) kuuteen korkeintaan pituutta n olevien lukujen summan tai erotuksen laskemiseen, sekä kaksi kantaluvun potenssilla kertomista. Olkoon T (n) yllä esitettyä ideaa hyödyntävän rekursiivisen kertolaskualgoritmin kompleksisuus. Silloin (i) toimii ajassa 2T (n/2) ja (iii) vaatii ajan O(n). Kohta (ii) on hieman ongelmallisempi. Kirjoitetaan n/2 + 1-pituiset luvut c ja d muodossa jolloin c = c 1 k + c 0 ja d = d 1 k + d 0, cd = c 1 d 1 k 2 + (c 1 d 0 + c 0 d 1 )k + c 0 d 0. Tulon c 1 d 1 laskeminen vaatii ajan T (n/2) ja muut laskutoimitukset onnistuvat ajassa O(n). Siispä kohta (ii) vaatii ajan T (n/2) + O(n). Näin ollen koko rekursiivisen algoritmin kompleksisuus toteuttaa yhtälön T (n) = 3 T (n/2) + O(n). Nyt lausetta 5.1 soveltamalla saadaan seuraava tulos.
37 5.4 Matriisien tulo 35 Lause 5.2. Probleema M(a, b), kahden n-pituisen luvun tulon laskeminen, kuuluu luokkaan O(n log 2 3 ) = O(n 1, ). Karatsuba-kertolasku on kaikkine yksityiskohtineen varsin monimutkainen algoritmi. Niinpä ainakin kynäpaperi-laskuissa koulualgoritmi lienee käytännössä nopeampi. Tietokoneimplementoinneissakin käsiteltävien lukujen on oltava varsin suuria (yli 1000 numeroisia), ennen kuin algoritmin hyödyt tulevat näkyviin Parannettu kertoalgoritmi Edellä nähtiin, että kertolasku voidaan laskea ainakin ajassa O(n log 2 3 ). Mutta osoittautuu, että se voidaan laskea vieläkin nopeammin. Käydään lyhyesti läpi periaate, joka osoittaa todeksi seuraavan lauseen. Lause 5.3. Olkoon ɛ > 0 vakio. On olemassa ajassa O(n 1+ɛ ) toimiva kertolaskualgoritmi. Ideana on konstruoida kullekin p:n arvolle algoritmi A p, jossa n-pituisten lukujen tulo palautuu 2p 1:n n/p-pituisten lukujen tulon laskemiseen (ynnä joitakin ajan O(n) vaativia laskutoimituksia). Tällöin saadaan rekursioyhtälö T (n) = (2p 1)T (n/p) + O(n), jonka ratkaisu lauseen 5.1 mukaan on O(n log p (2p 1) ). Koska lim log p p(2p 1) = 1, on selvää, että valitsemalla p riittävän suureksi saadaan kompleksisuuden yläräajaksi O(n 1+ɛ ). 5.4 Matriisien tulo Tässä syötteenä on kaksi n n-matriisia, ja tehtävänä on laskea niiden tulo. Merkitään probleemaa MatrM(A, B):llä. Mitataan kompleksisuus tarvittavien aritmeettisten operaatioiden (tulo ja summa) lukumäärän avulla. Tämä on perusteltua, jos matriisit ovat esimerkiksi Boolen matriiseja, siis 0, 1 alkioisia matriiseja. Tavanomaisesti laskien tarvittavien operaatioiden lukumäärä on n 2 (2n 1) = 2n 3 n 2 = Θ(n 3 ). Strassenin algoritmi vuodelta 1969 tarjoaa asymptoottisesti nopeamman metodin tulon AB laskemiseen. Myös tämä algoritmi perustuu hajoita jahallitse -ideaan.
38 5.4 Matriisien tulo 36 n 2 Olkoot siis n = 2 m, m N ja A sekä B n n-matriiseja. Jaetaan A ja B :n suuruisiin lohkoihin: A = A 11 A 12 ja B = B 11 B 12. A 21 A 22 B 21 B 22 Kerrottaessa A ja B tavanomaisesti lohkoesitystä käyttäen joudutaan laskemaan 8 tuloa ja 4 summaa käyttäen ( n 2 n 2 )matriiseja. Koska n nmatriisien summan laskeminen vaatii n 2 aritmeettista operaatiota, päädytään rekursioon ( n ) ( n ) 2 T (n) = 8 T + 4, 2 2 missä T (n) on algoritmin kompleksisuus. Lauseesta 5.1 saadaan ratkaisu T (n) = O(n 3 ), eli sama kompleksisuus kuin suoraviivaisella menetelmällä. Strassenin ideana oli pyrkiä vähentämään kalliimpien operaatioiden (tulojen) lukumäärää halvempien operaatioiden (summien) kustannuksella. Tähän päästään kaavoilla M 1 =(A 21 + A 22 A 11 )(B 22 B 12 + B 11 ), M 2 =A 11 B 11, M 3 =A 12 B 21, M 4 =(A 11 A 21 )(B 22 B 12 ), M 5 =(A 21 + A 22 )(B 12 B 11 ), M 6 =(A 12 A 21 + A 11 A 22 )B 22, M 7 =A 22 (B 11 + B 22 B 12 B 21 ), jolloin AB = M 2 + M 3 M 1 + M 2 + M 5 + M 6. M 1 + M 2 + M 4 M 7 M 1 + M 2 + M 4 + M 5 Tarvitaan siis 7 tuloa ja 24 summaa. (Itse asiassa esittelemällä uusia apumuuttujia yhteenlaskujen määrä voidaan pudottaa ainakin 15:een). Saadaan rekursio ( n ) ( n ) 2 T (n) = 7 T Nyt lause 5.1 antaa tuloksen T (n) = O(n log 7 ; n on kakkosen potenssi), ja siten ehdollisen kompleksisuuden lemman 2.1 nojalla T (n) = O(n log 7 ) = O(n 2,81 ).
39 5.5 Dynaaminen suunnittelu 37 Lause 5.4. n nmatriisien tulo voidaan laskea O(n log 7 ) aritmeettisella operaatiolla. Määräämällä Strassenin algoritmin kompleksisuuteen kätkeytyvät vakiot, jotka eivät ole kovin suuria, voidaan arvioida, milloin se on tavanomaista kertoalgoritmia nopeampi. Sittemmin on kehitetty yhä nopeampia algoritmeja matriisitulon laskemiseen. Esimerkiksi ns. CoppersmithWinograd algoritmi toimii ajassa O(n 2,376 ), mutta siihen kätkeytyvät vakiot ovat kovin suuria. Niinpä matriisien dimension n on oltava todella suuri, jotta näistä algoritmeista olisi käytännön hyötyä. 5.5 Dynaaminen suunnittelu Seuraavaksi tarkastellaan algoritmien suunittelu menetelmää, jota kutsutaan dynaamiseksi suunnitteluksi. Dynaamisen suunnittelun menetelmä muistuttaa hajoitajahallitse -menetelmää siinä, että ongelman ratkaisu saadaan yhdistämällä joidenkin osaongelmien ratkaisut. Hajoitajahallitse - algoritmeissa osaongelmat ratkaistaan rekursiivisesti, toisistaan riippumatta. Jos osaongelmilla on yhteisiäosaosaongelmia, nämä joudutaan ratkaisemaan useamman kerran. Dynaamisen suunnittelun idea on välttää tämä lisätyö taulukoimalla jo ratkaistujen osaongelmien vastaukset. 5.6 Binomikerroin Olkoon tehtävänä binomikertoimen ( ) n k = n! k!(n k)! laskeminen. Määrittelykaavaa käyttäen sitä ei kannata laskea, sillä osoittaja ja nimittäjä kasvavat nopeasti liian suuriksi. Parempi menetelmä saadaan hyödyntämällä kombinatoriikasta tuttua kaavaa ( ) ( ) ( ) n n 1 n 1 = + (0 < k < n). k k 1 k Se antaa välittömästi rekursiivisen tavan laskea binomikerroin. Algoritmi C (n, k): if k = 0 tai k = n then return C (n, k) = 1 else return C (n 1, k 1) + C (n 1, k) Mutta tässäkin menetelmässä on haittapuolensa. Monet arvot joudutaan laskemaan useaan otteeseen, jopa eksponentiaalisen monta kertaa. Tehokkaampi ratkaisu saadaan dynaamisen suunnittelun menetelmällä. Kaikki jo lasketut binomikertoimet taulukoidaan, jotta niitä ei tarvitse laskea enää uudelleen. Aloitetaan triviaaleilla C (0, 0) = C (1, 0) = C (1, 1) = 1. Aina kun kaikki luvut C (i, j), 0 j < i on laskettu, saadaan näiden avulla yhdellä yhteenlaskulla luvut C (i + 1, j). Tätä jatketaan, kunnes C (n, k) on
40 5.7 Matriisiketjun kertolasku 38 selvillä. (Jos menetelmä vaikuttaa tutulta, muistele kuinka Pascalin kolmio konstruoidaan.) Kuvaillulla menetelmällä binomikertoimen ( n k) laskemiseen tarvitaan Θ(n 2 ) yhteenlaskua. Pitää kuitenkin huomata, että yhteenlaskettavat luvut kasvavat eksponentiaalisesti. Erityisesti voidaan näyttää, että ( n n/2) 2 O(n). 5.7 Matriisiketjun kertolasku Tarkastellaan ongelmaa, missä on annettuna M 1, M 2,..., M n, missä M i on r i 1 r i matriisi. Tehtävänä on laskea tulo M = M 1... M n mahdollisimman vähillä operaatioilla. Oletetaan, että p q- ja q rmatriisien tulo vaatii pqr operaatiota. Kuten Strassenin algoritmi osoitti, tämä tulo voidaan laskea nopeamminkin ainakin neliömatriisien tapauksessa. Tässä ongelmassa ideana ei kuitenkaan ole tarkastella kahden matriisin tulon laskemista. Koska matriisitulo on assosiatiivinen, voidaan n matriisin tulo laskea (n 1)! eri järjestyksessä. Luonnollisesti kaikki järjestykset antavat saman vastauksen, mutta laskuun tarvittava työmäärä voi vaihdella huomattavasti. Esimerkki 5.3. Olkoot n = 4 ja (r 0, r 1, r 2, r 3, r 4 ) = (10, 20, 50, 1, 100). Laskemalla tulo järjestyksessä M 1 (M 2 (M 3 M 4 )) tarvitaan yhteensä operaatiota, kun taas järjestys (M 1 (M 2 M 3 )) M 4 vaatii vain 2200 operaatiota. Merkitään kertojärjestystä n 1pituisella jonolla, jonka alkiot ovat kokonaisluvut 1,..., n 1 jossakin järjestyksessä. Jonon ensimmäinen alkio kertoo, mikä kertolasku suoritetaan ensimmäisenä jne. Yllä olevan esimerkin järjestykset vastaavat jonoja 3, 2, 1 ja 2, 1, 3. Olkoon t i,j optimaalinen kertojärjestys tulolle M i M j. Nyt selvästi koko tulon optimaalinen järjestys on t 1,n = t 1,k, t k+1,n, k jollakin arvolla 1 k < n (jonot t j,j ajatellaan tyhjiksi). Ongelma voidaan tämän perusteella ratkaista rekursiivisesti. Silloin kuitenkin jotkin osaongelmat on ratkaistava useampaan otteeseen. Tehokkaampi menetelmä saadaan dynaamisella suunnittelulla ratkaisemalla optimaaliset järjestykset t i,j erotuksen j i mukaan kasvavassa järjestyksessä. Merkitään m i,j :llä järjestyksen t i,j vaatimien operaatioiden määrää. Selvästi 0 i = j m i,j =. min i k<j {m i,k + m k+1,j + r i 1 r k r j } i < j Tämä perustelee alla olevan algoritmin toimivuuden.
41 5.7 Matriisiketjun kertolasku 39 Algoritmi 5.1. Algoritmi matriisiketjun tulon laskemiseksi optimaalisessa järjestyksessä. syöte: matriisien dimensiot kertova jono (r 0, r 1,..., r n ) tuloste: t 1,n ja m 1,n for i = 1 to n do m i,i 0, t i,i tyhjä jono for l = 1 to n 1 do for i = 1 to n l do j i + l κ summan m i,k + m k+1,j + r i 1 r k r j minimoiva k, i k < j m i,j m i,κ + m κ+1,j + r i 1 r κ r j t i,j t i,κ, t κ+1,j, κ return t 1,n, m 1,n
42 40 6 Polynomien aritmetiikkaa Aiemmin esitetyt algoritmit ovat käsitelleet etupäässä lukuja. Toinen yleisesti esiintyvä matemaattinen perusrakenne on polynomit. Esimerkiksi koodausteoriassa ja kryptograassa käsiteltävät alkiot ovat usein jonkin äärellisen kunnan alkioita. Kunta-alkiot on kätevä esittää polynomeina, jolloin kuntaoperaatioiden (yhteen- ja kertolasku) implementointi vaatii polynomien aritmetiikkaa. 6.1 Polynomien summa ja tulo Tarkastellaan yhden muuttujan polynomeja P a (x) = a 0 + a 1 x a n 1 x n 1 R[x], missä kertoimet a i ovat jonkin renkaan R alkioita (esim. R = Z tai R = Z m ). Jatkossa, ellei muuta mainita, merkinnällä P c tarkoitetaan aina jotakin korkeintaan astetta n 1 olevaa polynomia, jonka kertoimina ovat alkiot c i (i = 1,..., n 1). Polynomi P a määräytyy yksikäsitteisesti sen kertoimista. Ohjelmoitaessa polynomit usein esitetäänkin vektorina, jonka ensimmäinen alkio kertoo polynomin asteen ja loput alkiot ovat polynomin kertoimet a i. Algoritmien yhteydessä polynomin koko on kuitenkin tapana määritellä sen kertoimien lukumääräksi; siis n 1 asteisen polynomin koko on n. Näin siitäkin huolimatta, että joissakin tapauksissa (R = Z) ei ole ylärajaa edes yhden kertoimen a i esittämiseen tarvittavien muistipaikkojen määrälle. Polynomialgoritmien kompleksisuutta arvioitaessa lasketaan tarvittavien rengasoperaatioiden määrää. Ajatellaan siis, että yksi yhteen- tai kertolasku R:ssä vaatii yhden aikayksikön riippumatta operoitavien alkioiden koosta. Polynomien yhteenlasku Kahden polynomin summa lasketaan ilmeisellä tavalla samanasteisten termien kertoimien summat: n 1 P a (x) + P b (x) = (a i + b i )x i, Näin ollen yhteenlasku onnistuu tasan n:llä kerroinrenkaan R yhteenlaskulla. Vähemmän ei varmasti riitä, joten Polynomien yhteenlasku -ongelma PolA(p, q) kompleksisuus on kertalukua Θ(n). i=0
43 6.2 Diskreetti Fouriermuunnos 41 Polynomien kertolasku Kahden n 1asteisen polynomin P a ja P b tulo voidaan laskea kaavasta P a (x) P b (x) = 2n 2 i=0 c i x i, missä c i = j+k=i a j b k. Tulo voidaan siss laskea kokonaislukujen tulon koulualgoritmia mukaillen. Ensin jokaisella b i :llä kerrotaan jokainen a j (n 2 tuloa). Sitten samanasteiset termit summataan yhteen (n 2 (2n 1) = (n 1) 2 summaa). Tarvitaan siis yhteensä n 2 +(n 1) 2 renkaan R operaatiota. Tämän perusteella polynomien kertolasku -probleema, merkitään PolM, kuuluu luokkaan O(n 2 ). Osoitetaan seuraavaksi, että PolM kuuluu ainakin luokkaan O(n log n). 6.2 Diskreetti Fouriermuunnos Nopea polynomien kertolasku algoritmia varten tarvitsemme hieman syvällisempää teoriaa. Edellä polynomit samaistettiin niiden kertoimien muodostaman vektorin kanssa: P a (a 0, a 1,..., a n 1 ). Tätä kutsutaan P a :n kerroinesitykseksi. Tämä ei kuitenkaan ole ainoa tapa esittää polynomi. Toinen saadaan antamalla polynomin arvo n:ssä eri pisteessä x i (i = 0, 1,..., n 1); siis P a (α 0, α 1,..., α n 1 ), missä α i = P a (x i ). Saatu esitys on yksikäsitteinen, jos yhtälöryhmällä P c (x i ) = α i (i = 0, 1,..., n 1) on ainoana ratkaisuna c = a. Tätä voidaan tutkia lineaarialgebrasta tutuilla työkaluilla. Kuten tullaan näkemään, sopivilla alkioiden x i valinnoilla polynomi tosiaan määräytyy yksikäsitteisesti αvektorista. Polynomin arvoesityksessä on se hyvä puoli, että kertolasku on nyt helppoa. Olkoot P a ja P b kaksi n-pituista polynomia, joiden arvoesitykset ovat P a (P a (x 1 ), P a (x 2 ),..., P a (x n )) ja P b (P b (x 1 ), P b (x 2 ),..., P b (x n )). Koska (P a P b )(y) = P a (y) P b (y), saadaan, että P a P b (P a (x 1 )P b (x 1 ), P a (x 2 )P b (x 2 ),..., P a (x n )P b (x n )), joten tulopolynimin arvoesitys saadaan laskemalla n tuloa. Ongelmaksi muodostuu arvoesityksen muuntaminen kerroinesitykseksi (ja päinvastoin). Suoraviivainen menetelmä kunkin α i :n laskemiseksi vaatii Ω(n) operaatiota, joten tällä tapaa kaikkien α i :tten laskeminen vie ajan Ω(n 2 ). Polynomien kertolaskua ajatellen näin ei saavuteta mitään etua. Mutta nopeamminkin selvitään, kunhan kerroinrengas R ja luvut x i on sopivasti valittu.
44 6.2 Diskreetti Fouriermuunnos 42 Määritelmä 6.1. Olkoot R kommutatiivinen rengas, n 1 ja n 1 R renkaan R yksikkö. Alkio ω R on primitiivinen n:s ykkösenjuuri, jos (i) ω n = 1; ja (ii) ω i 1 ei ole nollanjakaja R:ssä millään i = 1,..., n 1. Jos R on kunta (tai yleisemmin kokonaisalue), ehto (ii) on yhtäpitävä luonnollisemmalta tuntuvan ehdon ω i 1 kaikilla i = 1,..., n 1 kanssa. Esimerkki 6.1. Jos R = C, niin esimerkiksi e 2πi/n on primitiivinen n:s ykkösenjuuri. Olkoot n ja ω 1 kakkosen potensseja, sekä m = ω n Silloin voidaan todistaa, että ω on primitiivinen n:s ykkösenjuuri renkaassa Z m. Silloin on myös ω n 2 = 1 mod m, aivan kuten kaikilla kunnan primitiivisillä ykkösenjuurilla. Seuraava lemma kertoo primitiivisistä ykkösenjuurista juuri sen ominaisuuden, jota jatkossa tarvitaan. Lemma 6.1. Olkoon ω primitiivinen n:s ykkösenjuuri ja 1 l < n. Silloin n 1 ω lj = 0. j=0 Todistus. Suoralla kertolaskulla nähdään, että aina n 1 (x 1) x j = x n 1. j=0 Sijoittamalla x = ω l saadaan väite, sillä määritelmän nojalla ω l 1 ei ole nollanjakaja. Siirrytään tarkastelemaan diskreetin Fouriermuunnoksen ominaisuuksia. Jatkossa polynomi P a samaistetaan sen kertoimista muodostetun vektorin a = (a 0,..., a n 1 ) kanssa. Määritelmä 6.2. Olkoon R kommutatiivinen rengas ja ω sen primitiivinen n:s ykkösenjuuri. Kuvaus F ω : R n R n, F ω (P a ) = ( P a (1), P a (ω), P a (ω 2 ),..., P a (ω n 1 ) ) on diskreetti Fouriermuunnos (DFT) ykkösenjuuren ω suhteen. Merkitään α = (α 0,..., α n 1 ), missä α i = P a (ω i ) = j a jω ij. Olkoon A matriisi A = (ω ij ) n n. Silloin kuvaus F ω voidaan kirjoittaa matriisimuodossa F ω (a) = α = a (ω ij ) = a A. F ω siis muuttaa P a :n kerroinesityksen sen arvoesitykseksi laskemalla polynomin arvot pisteissä, jotka ovat primitiivisen n:nnen ykkösenjuuren ω potensseja. Pisteiden valinnasta seuraa, että kuvauksella F ω on käänteiskuvaus.
45 6.3 Nopea Fouriermuunnos 43 Lemma 6.2. F 1 ω on olemassa ja F 1 ω (α) = α A 1, missä (A 1 ) ij = 1 n ω ij. Todistus. Riittää näyttää, että A:n käänteismatriisi on 1 n (ω ij ). Merkitään S = A 1 n (ω ij ). Pitää siis osoittaa, että A = I n, eli että S ij = 1 n 1 ω ik ω kj 0, i j =. n k=0 1, i = j Tarkastellaan ensin tapausta i = j, S ii = 1 n 1 ω ik ki = 1 n 1 1 = 1. n n k=0 Kun i > j saadaan primitiivisen ykkösenjuuren määritelmän nojalla k=0 S ij = 1 n 1 ω k(i j) = 1 n n 0 = 0. k=0 Samaan tulokseen päästään tapauksessa i < j, kun kerrotaan summan termit luvuilla ω kn = 1: S ij = 1 n 1 ω k(i j) ω kn = 1 n 1 ω k(n+i j) = 0. n n k=0 Huomautettakoon vielä, että primitiivisen ykkösenjuuren määritelmässä vaadittiin, että n = n 1 on yksikkö; siispä 1 n on olemassa. Sen lisäksi, että DFT F ω on kääntyvä, edellinen lemma kertoo, että käänteismuunnos IDFT Fω 1 lasketaan oleellisesti samalla tavalla kuin F ω. Tarkemmin sanottuna Fω 1 = 1 n F ω 1. k=0 Myös ω 1 on n:s primiriivinen ykkösenjuuri renkaassa R. Esimerkki 6.2. Tiedetään, että 2 on kolmas primitiivinen ykkösenjuuri renkaassa Z 7. Olkoon P (x) = 1 + 3x + x 2. Lasketaan F 2 (P (x)). 6.3 Nopea Fouriermuunnos Seuraavaksi näytetään, kuinka DFT (ja siten myös IDFT) voidaan laskea nopeasti. Algoritmi, josta käytetään nimeä nopea Fouriermuunnos, FFT, perustuu sekin hajoitajahallitse -metodiin. Olkoon P a (x) = a 0 +a 1 x+...+a n 1 x n 1. Tehtävänä on siis laskea luvut α i = P a (ω i ) (i = 0,..., n 1), missä ω on R:n primitiivinen n:s ykkösenjuuri. Oletetaan, että n on kakkosen potenssi.
46 6.3 Nopea Fouriermuunnos 44 Voidaan kirjoittaa P a (x) = (a 0 + a 2 x a n 2 x n 2 ) + (a 1 x + a 3 x a n 1 x n 1 ) = P a(x 2 ) + xp a (x 2 ), missä P a ja P a ovat astetta n 2 1. Nyt P a (ω i ) = P a(ω 2i ) + ω i P a (ω 2i ) P a (ω n 2 +i ) = P a(ω n+2i ) + ω n 2 +i P a (ω n+2i ) = P a(ω 2i ) + ω n 2 +i P a (ω 2i ) (4) missä i = 0,..., n/2 1. Luvut P a (ω i ) (i = 0,..., n 1) saadaan siis laskemalla 1. luvut P a((ω 2 ) i ) ja P a ((ω 2 ) i ) i:n arvoilla 0, 1,..., n/2 1 ja 2. n kappaletta yhteenlaskuja ja vakiolla (ω:n potenssilla) kertomisia. Koska selvästi ω 2 on primitiivinen n 2 :s ykkösenjuuri, palautuvat tarvittavat P a:n ja P a :n arvojen laskemiset n 2 dimensioisten DFT:n laskemisiin. Lause 6.3. DFT ja IDFT F voidaan laskea ajassa O(n log n). Todistus. Olkoon T (n) edellä kuvaillun nopean Fouriermuunnoksen kompleksisuus. Edellä kerrotun perusteella T (n) toteuttaa rekursioyhtälön T (n) = 2 T ( n) + Θ(n). 2 Tämän ratkaisuna saadaan lausetta 5.1 soveltaen T (n) = Θ(n log n). Käänteinen muunnos IDFT tehdään lähes samalla tavalla kuin DFT. Yhtenä erona on käytettävän ykkösenjuuren (ω) vaihtaminen toiseksi (ω 1 ). Tämä ei aiheuta kompleksisuuteen muutoksia. Toinen ero on siinä, että IDFT:ssä pitää npituisen vektorin alkiot kertoa vakiolla 1 n, mikä siis vaatii vain n operaatiota. Näin ollen myös IDFT kuvaillulla algoritmilla vie ajan Θ(n log n). Esitetään vielä FFT algoritmimuodossa.
47 6.4 Polynomien nopea kertolasku 45 Algoritmi 6.1. Nopea Fouriermuunnos syöte: a = (a 0, a 1,..., a n 1 ) R n (n = 2 k ), ω R tuloste: α = F ω (a) R n kutsu: FFT ω (a) if n = 2 then return (a 0 + a 1, a 0 + ωa 1 ) if n > 2 then a (a 0, a 2,..., a n 2 ) a (a 1, a 3,..., a n 1 ) α FFT ω 2(a ), α FFT ω 2(a ) for i = 0 to n 2 1 do α i α i + ωi α i, α n 2 +i α i + ω n 2 +i α i return α = (α 0, α 1,..., α n 1 ) Mainittakoon vielä, että jos kerroinrengas R onkin kunta, helpottuu DFT:n laskeminen jonkin verran. Silloin nimittäin ω n 2 = 1, joten tällä luvulla kertomiset muuttuvat triviaaleiksi. Saatu säästö ei kuitenkaan vaikuta kompleksisuuden kertalukuun. 6.4 Polynomien nopea kertolasku Olkoot P a ja P b (n 1)asteisia polynomeja, ja olkoon niiden tulo 2n 2 asteinen polynomi P c (x) = 2n 2 i=0 c i x i, missä c i = j+k=i a j b k. Idea on laskea FFT:llä polynomien P a ja P b arvoesitykset, joista kertomalla vastinkomponentit saadaan tulopolynomin P c arvoesitys. Tästä päästään P c :n kerroinesitykseen tekemällä käänteinen Fouriermuunnos. Ideaa kuvaa alla oleva diagrammi. a, b F F(a), F(b)? c F 1 F(a) F(b) Koska P c :n aste on 2n 2, pitää sen arvoesityksessä olla (ainakin) 2n 1 pistettä. Näin ollen myös P a :n ja P b :n arvot tarvitaan yhtä monessa pisteessä.
48 6.4 Polynomien nopea kertolasku 46 Käytännössä tämä ratkaistaan niin, että kaikkien polynomien asteeksi ajatellaan 2n 1, ja näin ollen niitä vastaavat vektorit a, b ja c ovat 2npituisia. (Puuttuvien termien kertoimet asetetaan nolliksi). Algoritmi 6.2. Nopea algoritmi polynomien tulon laskemiseen. syöte: (n 1)asteiset polynomit P a, P b R[x] tuloste: tulopolynomi P c = P a P b a (a 0, a 1,..., a n 1, 0,..., 0), b (b 0, b 1,..., b n 1, 0,..., 0) α FFT ω (a), β FFT ω (b) for i = 0 to 2n 1 do γ i α i β i c 1 2n FFT ω 1(γ) return P c Koska nopean Fouriermuunnoksen kompleksisuus on O(n log n), on kertoalgoritmin kompleksisuus 3O(2n log 2n) + O(2n) = O(n log n). Esitetyssä kertoalgoritmissa on yksi puute: se toimii vain sellaisilla kerroinrenkailla R, joilla on primitiivisiä n:nnsiä ykkösenjuuria. Esimerkiksi kun R = Z, näin ei ole. Silloin voidaan kuitenkin toimia kompleksilukujen kunnassa C, jolloin tosin tarvitaan kompleksilukujen aritmetiikkaa. Toisaalta kompleksiluvutkin voidaan välttää sopivissa jäännösluokkarenkaissa Z m, joissa ykkösenjuuret voidaan määritellä (esimerkki 6.1). Lause 6.4. Polynomien kertolasku PolM kuuluu luokkaan O(n log n) SchönhageStrassen algoritmi Tarkastellaan jälleen kokonaislukujen kertolasku ongelmaa M(a, b). Kokonaisluvut voidaan luonnollisella tavalla ajatella polynomien arvoina tietyssä pisteessä. Esimerkiksi 123 = f(10), missä f(x) = x 2 + 2x + 3. Tätä yhteyttä käyttäen useat polynomeja koskevat tulokset voidaan modioida kokonaisluvuille sopiviksi. SchönhageStrassen algoritmi (v. 1971) lukujen kertolaskulle perustuu lukujen muuntamiseen polynomieksi ja polynomien kertolaskuun FFT:n avulla. Algoritmin kompleksisuus on O(n log n log log n). Ylimääräinen log log n kerroin polynomien kertolaskuun nähden aiheutuu siitä, että tulopolynomin x potenssien kertoimet eivät enää välttämättä ole 1-numeroisia. Tiedetään, että SchönhageStrassen algoritmi on Karatsuba ja Toom Cook algoritmeja nopeampi kun luvut ovat vähintään bittisiä. Vuonna
49 6.5 Muita polynomiprobleemoja löydetty Fürer'n algoritmi on kuitenkin asymptoottisesti nopein tunnettu kertolaskualgoritmi. Käytännössä lukujen pitää kuitenkin olla bittisiä ennen kuin se on nopeampi kuin SchönhageStrassen algoritmi. 6.5 Muita polynomiprobleemoja Tarkastellaan vielä joitakin polynomeihin liittyviä algoritmisia probleemoja. Tarkoituksena on lähinnä verrata niiden vaikeutta tulon laskemisen vaikeuteen. Tämä johtaa algoritmien teoriassa tärkeään redusoituvuuden käsitteeseen. Samaa redusoituvuutta tarvitaan esim. NP-täydellisyys todistuksissa. Määritellään aluksi joitakin polynomeihin liittyviä käsitteitä. Tarkastellaan polynomia p(x) K[x], missä K on kunta: p(x) = a 0 + a 1 x a n x n, a n 0, a i K. (Nyt siis tarkasteltavien polynomien aste on oletusarvoisesti n eikä n 1, kuten edellä). Jos m = deg(d(x)) deg(p(x)) = n ja d(x) ei ole nollapolynomi, voidaan tunnetusti kirjoittaa p(x) = q(x)d(x) + r(x), missä deg(q(x)) = n m ja deg(r(x)) < m. Lisäksi tämä esitys on selvästi yksikäsitteinen. Polynomi q(x) on osamäärä ja r(x) on jakojäännös jaettaessa p(x) polynomilla d(x). Osamäärää q(x) merkitään myös p(x) d(x). Polynomin p(x) 0 käänteisalkio p (x) on polynomi x p 2n (x) =. p(x) Selvästi deg(p (x)) = deg(p(x)), ja lisäksi x 2n = p(x) p (x) + r(x), missä deg(r(x)) < deg(p(x)). Erikoisesti tästä seuraa, että ( p (x) ) = p(x), joten p (x) on todella tietyssä mielessä polynomin p(x) käänteisalkio. Määritelmien perusteella suoraan laskemalla voidaan todeta seuraavat laskulait: Jos p(x), p 1 (x) ja p 2 (x) ovat mielivaltaisia polynomeja sekä d(x), d 1 (x) ja d 2 (x) nollasta poikkeavia polynomeja, niin L1: p 1 (x) d 1 (x) L2: p(x) d 1 (x) d 2 (x) ± p2 (x) d 2 (x) = = p(x) d 1 (x)d 2 (x) ; p1 (x)d 2 (x)±p 2 (x)d 1 (x) d 1 (x)d 2 (x) ;
50 L3: p 1 (x) p2 (x) d(x) = 6.5 Muita polynomiprobleemoja 48 p1 (x)d(x) p 2 (x) jos deg ( p 1 (x) ) 2 deg Jatkossa tarkastellaan seuraavia probleemoja. ( ) p2 (x) d(x). PolM(p, q): laskettava astetta n olevien polynomien p(x) ja q(x) tulo p(x)q(x); PolSqr(p): laskettava astetta n olevan polynomin p(x) neliö p(x) 2 ; PolInv(p): laskettava astetta n olevan polynomin p(x) käänteisalkio p (x); PolD(p, d): laskettava osamäärä jaettaessa korkeintaan astetta 2n oleva polynomi p(x) astetta n olevalla polynomilla d(x). Tavoitteena on osoittaa, että nämä neljä probleemaa ovat algoritmisesti yhtä vaikeita. Erikoisesti siis lauseen 6.4 nojalla ne voidaan ratkaista O(n log n) aritmeettisella operaatiolla. On syytä huomata, että tavanomaisin menetelmin kukin näistä ratkeaa O(n 2 ) aritmeettisella operaatiolla. Termi algoritmisesti yhtä vaikea formuloidaan seuraavasti: Olkoot P ja P' kaksi algoritmista probleemaa. Sanotaan, että probleema P redusoituu lineaarisesti probleemaan P', merkitään P l P', jos kaikille funktioille T : N N on voimassa ehto P' ratkeaa ajassa O ( T (n) ) = P ratkeaa ajassa O ( T (n) ). Edelleen sanotaan, että P ja P' ovat lineaarisesti ekvivalentit, merkitään P l P', jos P l P' ja P' l P. Redusoituvuus todistuksien idea on seuraava. Ongelman P tapaus I ratkaistaan redusoimalla tapaus sellaiseen muotoon, että se voidaan ratkaista käyttäen ongelman P' algoritmia, jonka oletetaan toimivan ajassa T (n). Kun tämä reduktio on lineaarinen (siis kompleksisuutta O(n), tai ainakin O(T (n))), saadaan näin ajassa O(T (n)) toimiva algoritmi ongelmalle P. Esimerkiksi osoitamme, että PolInv l PolM. Todistuksessa oletetaan, että probleemalle PolM on olemassa ajassa T (n) toimiva algoritmi, ja sen jälkeen osoitamme, että probleema PolInv polynomille p(x) voidaan ratkaistaan siten, että p (x) lasketaan käyttäen kertolaskua ja O(n) ajassa laskettavia operaatioita. Näin saamme ajassa O(T (n)) toimivan algoritmin probleemalle PolInv. Lineaarinen redusoituvuus on esimerkki algoritmien teoriassa usein esiintyvästä redusoituvuudesta. Intuitiivisesti tällöin probleeman ratkaisu palautetaan jo tunnettuun toisen probleeman ratkaisuun ja itse muunnoksen kompleksisuus ei ylitä ongelman kompleksisuutta. Huomautus 6.1. Yllä oleva määritelmä on hyvin yleinen, sillä siinä ei aseteta funktiolle T (n) mitään rajoituksia. Täten lineaarisen redusoitavuuden osoittaminen tulee usein hyvin hankalaksi. Niinpä käytännössä, kuten myös
51 6.5 Muita polynomiprobleemoja 49 tässä monisteessa, rajoitutaan kauniisti käyttäytyviin funktioihin T (n). Niinpä jatkossa oletetaan tätä eksplisiittisesti mainitsematta että tarkastelemamme kompleksisuusfunktiot ovat lopulta eiväheneviä ja toteuttavat ehdon 1) T (n) on b-sileä halutulla b:llä, ts. T (bn) = O ( T (n) ) ; ja/tai 2) T ( n 2 ) α T (n) jollekin vakiolle α < 1. Kaikki polynomit ja esimerkiksi funktio T (n) = n log n toteuttavat nämä ehdot. Aloitetaan yksinkertaisella esimerkillä. Lemma 6.5. PolM l PolSqr (olettaen, että kunnan K karakteristika char(k) 2). Todistus. Koska PolSqr on probleeman PolM erikoistapaus, on reduktio PolSqr l PolM selvä. Käänteinen reduktio todistetaan seuraavasti: oletetaan, että PolSqr ratkeaa ajassa O(T (n)). Nyt ( p(x) + q(x) ) 2 ( p(x) q(x) ) 2 = 4p(x)q(x), joten ( ) 2 ( ) 2 p(x) + q(x) p(x) q(x) p(x) q(x) =. 4 (Oletusta char(k) 2 tarvitaan, jotta K:n alkiolla 4 = 4 1 K voidaan jakaa.) Selvästi nyt PolM voidaan ratkaista ajassa 2O ( T (n) ) + 4O(n) = O ( T (n) ) suorittamalla 2 neliöintiä ja 4 lineaariaikaista algoritmia summaan, erotukseen ja vakiolla jakamiseen. ja Osoitetaan seuraavaksi reduktiot PolM l PolSqr l PolInv l PolM PolInv l PolD l PolInv, mitkä osoittavat kaikki tarkasteltavat probleemat lineaarisesti ekvivalenteiksi. Lemma 6.6. PolSqr l PolInv.
52 6.5 Muita polynomiprobleemoja 50 Todistus. Oletetaan, että PolInv voidaan ratkaista ajassa T (n). Olkoon p(x) n-asteinen polynomi, jolloin polynomi x 2n p(x) on astetta 3n. Näin ollen ( x 2n p(x) ) x 6n x 4n = x 2n =, p(x) p(x) ja vastaavasti (x 2n( p(x) + 1 )) = x 4n p(x) + 1 Laskukaavaa L1 käyttäen saadaan ( x 2n p(x) ) (x 2n( p(x) + 1 )) x 4n x 4n = p(x) p(x) + 1 (L1) x 4n ( p(x) + 1 ) x 4n p(x) = p(x) ( p(x) + 1 ) x 4n = p 2 = ( p 2 (x) + p(x) ), (x) + p(x) missä viimeinen identiteetti seuraa siitä, että polynomin p 2 (x) + p(x) aste on 2n. Nyt ottamalla molemmista puolista käänteisalkiot, saadaan [ (x 2n p(x) ) ( x 2n( p(x) + 1 )) ] = (( p 2 (x) + p(x) ) ) = p 2 (x) + p(x), josta seuraa, että p 2 (x) =. [ (x 2n p(x) ) ( x 2n( p(x) + 1 )) ] p(x). Siis neliö p 2 (x) voidaan laskea määräämällä kahdesti käänteisalkio astetta 3n oleville polynomeille, kerran sama astetta 2n olevalle polynomille sekä joitakin yhteen- ja vähennyslaskuja sekä potenssilla kertomisia. Siis PolSqr voidaan ratkaista ajassa 2 T (3n) + T (2n) + O(n) = O ( T (n) ), kun oletetaan, että T (n) on 2- ja 3sileä. Yllä olevasta todistuksesta on syytä huomata, että käytetty reduktio on analoginen reaalilukukaavan kanssa. Lemma 6.7. PolInv l PolD. a 2 = ( a 1 (a + 1) 1) 1 a
53 6.5 Muita polynomiprobleemoja 51 Todistus. Tällä kertaa PolInv on PolD:n erikoistapaus, joten reduktio PolInv l PolD on triviaali. Kääntäen oletetaan, että PolInv voidaan ratkaista ajassa T (n) toimivalla algoritmilla. Olkoon pari ( p(x), d(x) ) mielivaltainen probleeman PolD instanssi, siis deg(p(x)) 2n ja deg(d(x)) = n. Tehtävänä on laskea polynomi p(x) d(x). Olkoon r(x) jakojäännös jaettaessa x 2n polynomilla d(x), siis x d 2n (x) = d(x) = x2n r(x), d(x) missä deg(r(x)) < n. Nyt saadaan d (x)p(x) x 2n p(x) r(x)p(x) x 2n = x 2n d(x) (L1) x 2n p(x) r(x)p(x) = x 2n d(x) x 2n. d(x) Koska deg(r(x)) < n, on deg ( r(x)p(x) ) < 3n = deg ( x 2n d(x) ). Tästä seuraa, että r(x)p(x) x 2n = 0, d(x) joten p(x) d (x)p(x) = d(x) x 2n Halutun osamääräpolynomin p(x) d(x) laskemiseksi riittää siis suorittaa yksi n asteisen polynomin käänteisalkion laskeminen, yksi 2nasteisten polynomien tulon laskeminen ja yksi potenssilla x 2n jakaminen. Lemmojen 6.5 ja 6.6 mukaan PolM l PolInv, joten aika T (n) + O ( T (2n) ) + O(n) = O ( T (n) ) riittää; kun T (n) oletetaan 2sileäksi. Todistuksen reduktiolla on taas analogiansa reaalilukujen yhteydessä: x y = x y 1. Osoitetaan vielä vaikein (ja työläin) tarvittavista reduktioista. Lause 6.8. PolInv l PolM. Todistus. Oletetaan, että PolM voidaan ratkaista ajassa T (n) toimivalla algoritmilla. Tarkastellaan mielivaltaista nasteista polynomia p(x), jonka käänteisalkio pitää laskea. Oletetaan lisäksi, että n on muotoa 2 m 1, sekä merkitään k = n+1 2 = 2 m 1. Tällöin siis n = 2k 1.
54 6.5 Muita polynomiprobleemoja 52 Tiedetään, että deg ( x 2n p(x)p (x) ) < n = 2k 1. Konstruktion idea on, että määritellään polynomin q(x), jolle deg ( x 2n p(x)q(x) ) < n = 2k 1, jolloin välttämättä q(x) = p (x). Suoritetaan polynomin q(x) = p (x) konstruointi kahdessa vaiheessa. Vaihe I: Määritellään polynomi h(x) = x k p(x) x k Käyttäen laskusääntöä L3 saadaan että polynomin h(x) määritelmässä esiintyvä käänteisalkio p(x) = x2k 2 x 3k 2 =. p(x) x k p(x) x k Merkitään r(x):llä jakojäännöstä jaettaessa x 3k 2 polynomilla p(x), siis deg r(x) (n 1), ja r(x) toteuttaa yhtälön x 3k 2 p(x) = x3k 2 r(x) p(x). Nyt x 2n p(x)h(x) = x 4k 2 p(x)xk( x 3k 2 r(x) ) = x k r(x). p(x) Koska deg x k r(x) < k + n = k + 2k 1 = 3k 1, h(x) ei toteuta ehtoa ( ). Nähdään myös, että p(x)h(x) = x 2n x k r(x). Vaihe II: Seuraavaksi tarkennetaan polynomin p (x) likiarvo h(x) seuraavalla tavalla. Olkoon h 2 (x)p(x) q(x) = 2h(x) ( ) ja olkoon s(x) jakojäännös jaettaessa h 2 (x)p(x) polynomilla x 2n, jolloin siis, missä deg(s(x)) (2n 1). Saadaan h 2 (x)p(x) x 2n = h2 (x)p(x) s(x) x 2n. x 2n p(x)q(x) = 2p(x)h(x) p2 (x)h 2 (x) p(x)s(x) ( )( x 2n p(x)h(x) 2x 2n p(x)h(x) ) + p(x)s(x) = ( x 2n x 2n x k r(x) )( x 2n + x k r(x) ) + p(x)s(x) = ( x 2n x 4n x 2k r 2 (x) ) + p(x)s(x) = x 2n = x 2n + p(x)s(x) x2k r 2 (x) x 2n. ( )
55 6.5 Muita polynomiprobleemoja 53 Siis Koska x 2n p(x)q(x) = p(x)s(x) + x2k r 2 (x) x 2n. deg ( p(x)s(x) ) n+(2n 1) = 3n 1 ja deg ( x 2k r 2 (x) ) 2k+2(n 1) = 3n 1, huomataan, että deg p(x)s(x) + x2k r 2 (x) x 2n (3n 1) 2n n 1. Saadaan siis, että deg ( x 2n p(x)q(x) ) < n, joten q(x) = p (x). Yhdistämällä polynomien h(x) ja q(x) määritelmät saadaan kaava polynomin p(x) käänteisalkion laskemiseksi: p (x) = 2x k p(x) x k ( p(x) p(x) x k ) 2 x n 1. Siis p (x):n laskemiseksi riittää laskea astetta n k = n 1 2 olevan polynomin käänteisalkio; astetta n 1 2 olevan polynomin neliö (siis tulo), kuten myös astetta n olevien polynomien tulo; ja korkeintaan astetta n olevien polynomien erotus, x:n potenssilla kertominen ja jakaminen. Tässä on syytä huomata, että n 1 2 = 2 m 1 1 on samaa muotoa kuin n, joten saadaan rekursiivinen hajoitajahallitse -algoritmi polynomin p (x) laskemiseksi. Merkitään sen kompleksisuutta funktiolla g(n). Tällöin g(n) = g( n 1 2 n 1 n 1 ) + T (n) + T ( 2 ) + O(n) = g( 2 ) + O( T (n) ). Olettaen, että T (n) toteuttaa ehdon 2) sivulla 49, voidaan päätellä, että g(n) = O ( T (n) ). Tiedetään siis, että lemma on voimassa, kun polynomin p(x) aste on muotoa n = 2 m 1. Kun p(x) ei toteuta tätä ehtoa lasketaan p (x) seuraavasti. Olkoon i pienin sellainen luku, että n + i on muotoa 2 m 1, jolloin selvästi i < n ja siis n + i < 2n. Lasketaan q(x) = (x i p(x)) (onnistuu edellä mainitulla tavalla ajassa O(T (2n)) = O(T (n))) ja edelleen q (x) = (vie ajan O(n)). Osoitetaan että q (x) = p (x). q(x) x i
56 6.5 Muita polynomiprobleemoja 54 Ensinnäkin, q(x) = (x i p(x)) = x 2n+2i x i p(x) ja q (x) = x 2n+2i = x i p(x) q(x) + r(x), q(x) = x i q (x) + s(x), missä deg r(x) < n + i ja deg s(x) < i. Näin ollen q(x) x, joten i x 2n+2i = x i p(x) q(x) + r(x) = x i p(x) (x i q (x) + s(x)) + r(x) = x 2i p(x) q (x) + x i p(x)s(x) + r(x) ja jakamalla puolittain termillä x 2i, saadaan että x 2n p(x) q (x) = xi p(x)s(x) + r(x) x 2i. Nyt deg ( x i p(x)s(x) + r(x) ) < n + 2i, joten deg(x 2n p(x) q (x)) < n ja ehdon ( ) mukaan q (x) = p (x). Kuten aiemmin esitetyillä reduktioilla on tälläkin analogiansa reaalianalyysissä. Se noudattelee samoja suuntaviivoja kuin Newtonin menetelmä luvun a käänteisluvun laskemiseksi. Siinä siis tehtävänä on etsiä funktion f(x) = 1 ax nollakohta. Tämä hoidetaan seuraavasti: Arvataan likiarvo b, ja merkitään ab = 1 δ. Oletetaan, että δ < 1. Tarkennetaan arvausta laskemalla c = 2b b 2 a. Tarkennuksia voidaan jatkaa, kunnes on saavutettu haluttu tarkkuus. Luku c on todella parempi likiarvo a 1 :lle kuin b, sillä ac = a(2b b 2 a) = ab(2 ab) = (1 δ)(1 + δ) = 1 δ 2. Lauseen 6.8 reduktio oli vain sikäli parempi, että ensimmäisellä tarkennuksella saatiin heti tarkka arvo. Kokoamalla lemmat 6.5, 6.6, 6.7 ja 6.8 saadaan seuraava tulos. Lause 6.9. Probleemat PolM, PolSqr, PolInv ja PolD ovat lineaarisesti ekvivalentteja. Erikoisesti kukin niistä voidaan ratkaista O(n log n) aritmeettisella operaatiolla. Kuten edellä mainittiin, saadaan polynomialgoritmien avulla asymptoottisesti hyviä algoritmeja myös kokonaisluvuille. Esimerkiksi jakolaskun kompleksisuus voidaan todistaa samaksi kuin kertolaskun kompleksisuus polynomien avulla. Tarkastelut ovat kuitenkin hankalampia. Mainittakoon kuitenkin, että kaikki polynomeja koskevat tulokset eivät yleisty kokonaislukuihin. Esimerkiksi annettu nasteinen polynomi voidaan jakaa tekijöihin polynomiajassa toimivalla algoritmilla, mutta kokonaislukujen tekijöihinjakoon ei tunneta tehokasta menetelmää.
57 55 7 Alkulukutestaus ja todennäköisyysalgoritmit Tarkastellaan ongelmaa Prime (a), missä tehtävänä on päättää, onko syöte a alkuluku vai ei. Tätä ongelmaa käytettiin pitkään esimerkkinä ongelmasta, jolle ei tunnettu polynomiaikaista determinististä algoritmia, mutta joka ratkeaa tehokkaasti tnalgoritmilla. Kuitenkin vuonna 2002 AgrawalKayal Saxena löysivät tälle ongelmalle polynomiaikainen algoritmin. Seuraavaksi esitetään tämä ns. AKS-algoritmi ja sen jälkeen tarkastellaan tehokasta todennäköisyysalgoritmia Prime (a) ongelmalle. 7.1 AKSalgoritmi AKSalgoritmi perustuu seuraavaan lauseeseen. Lause 7.1. Olkoon syt(a, b) = 1. Luku a on alkuluku jos ja vain jos (x b) a x a b (mod a) (5) Todistus. Tarkastellaan polynomia (x b) a (x a b) (mod a). Newtonin binomikaavan mukaan termin x i kerroin on ( 1) i( a i) b a i, kun i = 1,..., a 1. Jos a on alkuluku, niin a jakaa luvun ( a i), joten (x b) a (x a b) b a b b b 0 (mod a). Jos a ei ole alkuluku, niin sillä sillä alkulukutekijä q. Nyt voidaan osoittaa (demonstraatiot), että a ei jaa lukua ( a q), joten (x b) a (x a b) 0 (mod a). Edellisestä lauseesta seuraa triviaali, algoritmi; tarkistetaan onko (x 1) a x a 1 (mod a). Tämä algoritmi ei kuitenkaan ole polynomiaikainen, sillä polynomissa (x b) a on a+1 = Θ(2 n ) termiä, kun n = a l = log a. Tämä voidaan kuitenkin välttää tarkastelemalla polynomia (x b) a myös modulo (x r 1), missä r = O(n k ). Tällöin joudutaan kuitenkin tarkastelemaan polynomia myös useammalle luvulle b. Perustelut sopivan luvun r olemassa ololle ovat melko pitkät ja tekniset ja ne sivuutetaan tässä. Todetaan vain, että luvuksi r kelpaa luku, joka (i) on alkuluku, (ii) syötteen a kertaluku modulo r on vähintäin 4 log 2 a + 2, jolloin (iii) pitää käydä läpi vaihtoehdot 1 b 2 r log a + 1. Alla AKS-alkulukutestaus algoritmin pseudokoodi.
58 7.2 Todennäköisyysalgoritmit 56 Algoritmi 7.1. AKS alkulukutestaus syöte: a Z tuloste: kyllätai ei kutsu: Prime if a = b c, b > 1 then return ei r 2 while r < n if syt(a, r) 1 then return ei if Prime(r) = kylläthen q luvun r 1 suurin alkutekijä if q > 4 r log a and a r 1 q 1 (mod r) then break r r + 1 for b = 1 to 2 r log a + 1 do if (x b) a x a b (mod x r 1, a) return ei return kyllä Voidaan osoittaa, että AKS-algoritmin kompleksisuus on O(n 12+ε ). Tietyillä parannuksilla algoritmi saadaan toimimaan ajassa O(n 6+ε ) ja jopa ajassa O(n 4+ε ) joillekin luvuille. Käytännössä AKS-algoritmi ja sen parannukset ovat kuitenkin liian hitaita. Alkulukutestaukselle on olemassa nopeita ja riittävän luotettavia todennäköisyysalgoritmeja, ja niitä käytetään käytännön sovelluksissa ja matemaattisissa ohjelmistoissa. Myöhemmin käsitellään erästä näistä alkulukutestaus algoritmeista, ns. MillerinRabinin alkulukutestiä. Huomautetaan vielä, että jos ns. yleistetty Riemannin hypoteesi pitää paikkaansa, on myös ns. Artinin konjektuuri priitiivisille juurille voimassa. Tästä seuraisi polynomiaikainen algoritmi alkulukutestaukselle. 7.2 Todennäköisyysalgoritmit Kaikki tähän asti esitetyt algoritmit ovat olleet deterministisiä: jos algoritmi ajetaan toistuvasti samalla syötteellä, suoritetaan jokaisella toistolla tarkalleen samat operaatiot. Niin sanotuissa todennäköisyysalgoritmeissa (lyhyemmin: tn-algoritmeissa) näin ei ole, vaan tietyissä kohdissa algoritmi voi tehdä satunnaisia syötteestä riippumattomia valintoja. Deterministisessä algoritmissa on aina pidettävä huoli siitä, että algoritmi ei voi joutua esimerkiksi ikuiseen luuppiin. Jos näin käy, ei kyseistä instanssia voida koskaan ratkaista sillä algoritmilla. Tnalgoritmeissa tästä ehdosta
59 7.2 Todennäköisyysalgoritmit 57 voidaan joustaa, kunhan pidetään huoli siitä, että ongelmatilanne esiintyy riittävän pienellä todennäköisyydellä kaikilla mahdollisilla instansseilla. Ongelmatilanteissa algoritmin suoritus voidaan aloittaa alusta, ja paremmalla onnella oikea vastaus löytyy. On ongelmia, joihin paras tunnettu ratkaisumenetelmä onkin juuri tällainen tnalgoritmi. Joissakin tapauksissa ei edes tunneta tehokasta determinististä algoritmia. Tn-algoritmit voidaan jakaa kolmeen eri luokkaan. Numeerisissa algoritmeissa satunnaisuutta käytetään numeeristen probleemojen likimääräiseen ratkaisemiseen. Monte Carlo -algoritmit (lyhyesti MCalgoritmit) soveltuvat lähinnä ratkeavuusprobleemoihin. Ne antavat aina jonkun vastauksen, mutta sen ei tarvitse olla oikea. Ollakseen hyödyllinen MCalgoritmin erehtymistodennäköisyys on voitava tehdä mielivaltaisen pieneksi (laskuaikaa pidentämällä). Las Vegas -algoritmit (LValgoritmit) eivät välttämättä aina anna vastausta (tai ilmoittavat en tiedä), mutta jos vastaus annetaan, se on aina oikea. Jälleen ollakseen hyödyllinen LValgoritmin erehtymistodennäköisyys on voitava tehdä olemattomaksi. MC- ja LValgoritmien yhteydessä ei ole järkevää määritellä kompleksisuutta pahimman tapauksen mukaan; teoriassa vastausten saaminen voi kestää äärettömän kauan. Parempi mittari saadaan, kun kunkin syötteen s kompleksisuudeksi otetaan tarvittavien alkeisoperaatioiden määrän odotusarvo E(s). Tnalgoritmin A kompleksisuus määritellään nyt funktiona T A (n) = max{e(s) s l = n}. (Huomaa, että tämä on eri asia kuin algoritmin keskimääräinen kompleksisuus.) Determinististen algoritmien yhteydessä polynomiajassa toimivia algoritmeja pidetään tehokkaina algoritmeina. Mutta samoin polynomiajassa toimiva tnalgoritmi on käytännössä toteutettava laskentamenetelmä, kunhan virhetodennäköisyys on pieni. (Formaalisesti vaaditaan, että tnalgoritmi toimii polynomiajassa ja samalla virhetodennäköisyys on pienempi kuin 1/P (n) millä tahansa polynomilla P.) Huomautus 7.1. Korostetaan vielä, että on väärin ajatella, että tnalgoritmien tuottamiin vastauksiin ei voi luottaa. Algoritmien virhetodennäköisyys saadaan mielivaltaisen pieneksi iteroimalla algoritmia riippumattomilla laskuilla. Näin saadaan haluttu varmuustaso pidentämällä jonkin verran käytettävää laskuaikaa. Tällä kurssilla tnalgoritmeja tarkastellaan lähinnä esimerkkien valossa.
60 7.3 Numeeriset satunnaisalgoritmit Numeeriset satunnaisalgoritmit Kuten aiemmin mainittiin, numeeriset algoritmit ovat yleensä likimääräisalgoritmeja. Tällaiset algoritmit eivät varsinaisesti kuulu tämän kurssin asioihin, joten aiheesta esitetään vain yksi esimerkki. Esimerkki 7.1. Olkoon tehtävänä laskea määrätty integraali I = 1 0 f(x)dx, kun kuvaus f : [0, 1] [0, 1] on annettu. (Oletetaan, että I on olemassa.) Tunnetusti I on suorien x = 0, y = 0, x = 1 ja käyrän y = f(x) rajoittaman kuvion pinta-ala. Sen likiarvo saadaan seuraavalla tn-algoritmilla. Merkintä x r (0, 1) tarkoittaa, että muuttuja x saa satunnaisen arvon reaalilukuväliltä (0, 1). Algoritmi 7.2. Likimääräisalgoritmi 1 0 f(x)dx laskemiseksi. syöte: iteraatioiden lukumäärä n tuloste: integraalin 1 0 f(x)dx likiarvo l 0 for i = 1 to n do x r (0, 1), y r (0, 1) if y f(x) then l l + 1 return l/n Algoritmin antaman likiarvon tarkkuus on selvästi sitä parempi, mitä suuremmaksi syöte n valitaan. 7.4 Monte Carlo -algoritmit Monte Carlo -algoritmit määriteltiin tnalgoritmeina, jotka saattavat joskus vastata väärin. Laskenta-aikaa lisäämällä virheen mahdollisuus saadaan kuitenkin mielivaltaisen pieneksi. MCalgoritmit soveltuvat parhaiten päätäntäongelmiin (vastaus kyllä tai ei). Usein tällaisilla MCalgoritmeilla toinen mahdollinen vastaus on aina oikea, ja toinen vastaus voi pienellä todennäköisyydellä olla virheellinen. Olkoon A algoritmi, jossa ei on aina oikea vastaus, mutta kyllä on väärä todennäköisyydellä ɛ. Silloin myös alla olevan algoritmin RepA vastaus ei on aina oikein, ja nyt vastaus kyllä on väärin todennäköisyydellä ɛ n. RepA(k, s) : for i = 1 to k do if A(s) = ei then return ei return kyllä
61 7.4 Monte Carlo -algoritmit 59 Siis toistamalla testiä A lineaarinen määrä samalla syötteellä pienenee virhetodennäköisyys eksponentiaalisesti. Jos A:n molemmat vastaukset voisivat olla virheellisiä, valittaisiin useammin toistunut vastaus. Silloin, jotta päästäisiin samaan luotettavuustasoon, tarvittaisiin toistoja enemmän Millerin-Rabinin alkulukutestaus Tarkastellaan ongelmaa Prime (a), missä tehtävänä on päättää, onko syöte a alkuluku vai ei. Edellä esitettiin jo Prime (a) probleemalle deterministinen, polynomiaikainen AKSalgoritmi. Käytännössä AKSalgoritmin kompleksisuus on liian suuri ja on kannattavampaa käyttää tehokasta tnalgoritmia. Olkoon P alkulukujen joukko. Kun a on positiivinen kokonaisluku, niin multiplikatiivinen jäännösluokkaryhmä modulo a on Z a = {x Z 1 x < a, syt(x, a) = 1}. Tarkastelujen lähtökohtana on tunnettu Fermat'n pieni lause: a P = [ x : syt(x, a) = 1 x a 1 1 (mod a) ]. Lukuja x, joille syt(x, a) = 1 ja x a 1 1 (mod a), kutsutaan luvun a P todistajiksi. Jos a on alkuluku, kaikki Z a:n alkiot ovat Ptodistajia. Mutta myös yhdistetyllä luvulla a on aina Ptodistajia (esim. x = 1). Joka tapauksessa luku a voidaan todistaa yhdistetyksi esittämällä yksikin luku x, joka ei ole a:n Ptodistaja. Koska syt:n laskeminen ja modulaarinen potenssiinkorotus onnistuu polynomiajassa, tulee mieleen seuraavanlainen polynomiaikainen tnalgoritmi. FTest(k, a) : for i = 1 to k do x r {2, 3,..., n 1} if syt(x, a) > 1 tai x a 1 1 (mod a) then return a P return a P Edellisen algoritmin kompleksisuus on O(kn 3 ). Sen virhetodennäköisyys on hankalampi laskea. Yllä olevan perusteella eivastaus (a P) on aina oikea. kyllävastausten oikeellisuutta voidaan arvioida vasta, kun tiedetään, paljonko yhdistetyllä luvulla voi olla Ptodistajia. Voidaan osoittaa, että yleensä niitä on varsin vähän. Mutta ikävä kyllä on joitakin lukuja ns. Carmichaelin luvut joilla kaikki Z a:n luvut ovat Ptodistajia. Näin ollen, jos syötteenä on Carmichaelin luku, algoritmi FTest epäonnistuu varsin suurella todennäköisyydellä. Luotettavan alkulukutestin konstruoimiseen tarvitaan siis jotain muuta. Yllä olevaa menetelmää ei tarvitse muuttaa kovinkaan paljon. Olkoon a > 4 pariton, ja olkoon a 1 = 2 s t, missä t on pariton. Määritellään joukko B(a), missä x B(a), jos 2 x a 2 ja
62 7.4 Monte Carlo -algoritmit 60 x t 1 (mod a); tai x 2it 1 (mod a) jollakin 0 i < s. Alla esitetyllä algoritmilla inb(x, a) voidaan nopeasti testata, kuuluuko alkio x joukkoon B(a). inb(x, a) : s 0, t a 1 repeat s s + 1, t t/2 until t on pariton y x t mod a if y = ±1 then return kyllä for i = 1 to s 1 do y y 2 mod a if y = 1 then return kyllä return ei Seuraava lause kertoo, miksi joukko B(a) on hyödyllinen. (Todistus sivuutetaan.) Lause 7.2. Olkoon a > 4 pariton. Silloin, jos a on alkuluku, niin B(a) = {2,..., a 2}. Jos a on yhdistetty luku, niin B(a) a 9 4. Joukon B(a) alkioita kutsutaan luvun a vahvoiksi Ptodistajiksi. Nyt siis joukon {2,..., a 2} luvuista kaikki ovat vahvoja Ptodistajia, jos a on alkuluku. Jos taas a on yhdistetty, niin poikkeuksetta alle neljännes näistä luvuista on vahva Ptodistaja. Niin kutsuttu MillerinRabinin alkulukutesti hyödyntää tätä ominaisuutta. Algoritmi 7.3. MillerinRabinin alkulukutesti. syöte: pariton kokonaisluku a > 4, toistojen määrä k tuloste: a P? for i = 1 to k do x r {2,..., a 2} if inb(x, a) = ei then return a P return a P Merkitään taas a l = n. Algoritmin inb(x, a) kompleksisuus on selvästi O(n 3 ), joten MillerinRabinin alkulukutesti toimii ajassa O(kn 3 ). Jos a P, niin algoritmi vastaa aina oikein; jos a P, niin algoritmi voi väittää sitä alkuluvuksi korkeintaan todennäköisyydellä 4 k.
63 7.5 Las Vegas -algoritmit 61 Alkulukutestaukseen on olemassa useita muitakin tnalgoritmeja. Mainittakoon mm. SolowayStrassen alkulukutesti, joka toimii samassa ajassa kuin MillerinRabinin testi, mutta sen virhetodennäköisyys on 2 k. Myös deterministisiä testejä on olemassa AKSalgoritmin lisäksi, mainittakoon esim. LucasLehmerin testi sekä elliptisten käyrien alkulukutesti. 7.5 Las Vegas -algoritmit Las Vegas -algoritmit ovat siis tnalgoritmeja, jotka eivät koskaan vastaa väärin. Joillakin suorituskerroilla ne voivat kuitenkin joutua umpikujaan, jolloin ne luovuttavat. Tämä ei haittaa, kunhan luovuttamisen todennäköisyys ei ole kohtuuttoman suuri. Algoritmi voidaan suorittaa uudestaan, samalla syötetteellä, uusilla satunnaisilla valinnoilla, kunnes ratkaisu löytyy Kokonaislukujen tekijöihinjako Luvun tekijöihinjakoon liittyy kaksi algoritmista probleemaa: Split (a) ja Factorize (a). Edellisessä pyritään löytämään jokin eitriviaali tekijöihinjako a = bc (b, c > 1), kun taas jälkimmäisessä tehtävänä on löytää a:n alkutekijähajotelma. On ilmeistä, että ongelman Split (a) ratkaiseva algoritmi yhdistettynä alkulukutestiin ratkaisee ongelman Factorize (a). Niinpä keskitymme ongelmaan Split (a). Split (a):lle on triviaali deterministinen ratkaisualgoritmi. TrivSplit(a) : for i = 2 to a do if i jakaa a:n then return a = i a i return a P Testejä joudutaan tekemään pahimmassa tapauksessa a = 2 n/2 kappaletta. Jos a:lla ei ole pieniä alkutekijöitä, ei tätä algoritmia voi käyttää. Itse asiassa Split (a):lle ei edes tunneta tehokkaita algoritmeja, sen paremmin deterministisiä kuin tnalgoritmeja. Mutta parempaa kuin TrivSplit toki on kehitetty. Seuraavaksi esitettävä Pollardin ρ -menetelmä on LValgoritmi ja se löytää suuruusluokkaa O(B 2 ) olevien lukujen tekijät samassa ajassa kuin TrivSplit ratkaisee ongelman O(B)-kokoisilla luvuilla. Olkoon f : S S satunnainen funktio ja merkitään S = n. Määritellään jono (x i ) rekursiivisesti ehdosta x i = f(x i 1 ), missä i = 1, 2,... (luku x 0 voidaan valitaan satunnaisesti). Koska joukko S on äärellinen, on oltava indeksit i ja j, joille x i = x j (ns. törmäys). Näin ollen jono koostuu hännästä x 0, x 1,..., x i 1, jota seuraa loputtomasti toistuva sykli x i,..., x j 1. Voidaan todistaa (sivuutetaan), että sekä hännän että syklin pituuden odotusarvo on πn/8 = O( n).
64 7.5 Las Vegas -algoritmit 62 Siirrytään tarkastelemaan ongelmaa Split (a). Määritellään jono (x i ) ehdoista x 0 = 2, x i+1 = f(x i ) = x 2 i + 1 (mod a) (i 1). Olkoon α jokin a:n tekijä, ja määritellään toinen jono (y i ), missä y i = x i (mod α). Nyt siis (y i ) on määritelty joukossa Z α, joten siitä löytyy (todennäköisesti) törmäys y i = y j indeksillä i = O( α). Koska tekijää α ei tunneta, jonon (y i ) alkioita ei voida laskea. Mutta törmäys voidaan silti havaita tehokkaasti käyttämällä jonoa (x i ). Jos nimittäin y i = y j, niin syt(x i x j, a) > 1. Tällöin, jos vielä syt(x i x j, a) < a, niin a:n ei-triviaali tekijä on löytynyt. (Tapauksen syt(x i x j, a) = a todennäköisyys on hyvin pieni.) Yksi tapa etsiä törmäys jonosta (y i ) on laskea jonon (x i ) luvut tiettyyn rajaan asti ja sitten laskea syt(x i x j, a) kaikille pareille i, j < k. Mutta käytännössä lukujen x i tallettaminen muodostuu pullonkaulaksi. Toimivampi menetelmä on etsiä pelkästään muotoa y i = y 2i olevia törmäyksiä. Tällöin riittää pitää kerralla muistissa vain luvut x i ja x 2i. Jos syt(x i x 2i, a) = 1, lasketaan x i+1 ja x 2(i+1) (x i sekä x 2i voidaan unohtaa) ja jatketaan prosessia. Esitetään yllä kuvailtu menetelmä vielä algoritmina. Algoritmi 7.4. Pollardin ρ -algoritmi. syöte: yhdistetty luku a tuloste: luvun a eitriviaali tekijä u 2, v 2 for i = 1 to... do u u (mod a) v v (mod a), v v (mod a) d syt(u v, a) if 1 < d < a then return d if d = a then quit (ei onnistunut!) Jos algoritmi ei löydä ei-triviaalia tekijää, voidaan kokeilla muutakin funktiota kuin f(x) = x (mod a). Esimerkki 7.2. Tarkastellaan lukua a = Alla olevassa taulukossa
65 7.5 Las Vegas -algoritmit 63 on muuttujien u, v ja d arvot algoritmin for-silmukoiden jälkeen. u v d Algoritmi siis löysi a:n tekijän α = 743. Toinen tekijä saadaan laskemalla β = n/α = 613. Käyttämällä jotakin alkulukutestiä voidaan löydetyt luvut varmentaa alkuluvuiksi, joten a:n alkutekijähajoitelma on löytynyt. Pollardin ρ on Las Vegas -algoritmi, sillä selvästi sen antama vastaus on aina oikea. Tosin ei ole mitenkään selvää, että algoritmi tuottaa aina tuloksen Neliöjuuri ryhmässä Z p Olkoon p > 2 alkuluku. Tarkastellaan multiplikatiivista jäännösluokkaryhmää Z p = {a Z 1 a < p, syt(a, p) = 1}. Neliönjäännökset modulo p määritellään alkioina a 2 (mod p), missä a Z p. Jos a Z p ei ole neliönjäännös, sen sanotaan olevan neliönepäjäännös. Merkitään neliönjäännösten joukkoa QR p ja epäjäännösten QNR p. Seuraavat tulokset ovat tuttuja lukuteorian alkeista. Z p = < g > = {1, g, g 2,..., g p 1 } jollakin g Z p. QR p = QNR p = p 1 2. QR p = {x 2 (mod p) x = 1, 2,..., p 1 2 }. x QR p x p (mod p); x QNR p x p (mod p). Yllä olevasta on helppo päätellä, että jos a QR p, niin yhtälöllä x 2 a (mod p) on aina tasan kaksi ratkaisua. Näitä lukuja kutsutaan a:n neliöjuuriksi modulo p. Selvästi nämä neliöjuuret ovat muotoa ±α = α, p α. Näin ollen tarkalleen toinen neliöjuurista on välillä [1, p 1 2 ]. Merkitään sitä symbolilla a.
66 7.5 Las Vegas -algoritmit 64 Kun p ja x Z p on annettu, on helppo ratkaista, onko x:llä neliöjuuria modulo p: riittää laskea luku x p 1 2 (mod p). Tämä onnistuu ajassa O(n 3 ), kun oletetaan että 0 < x < p ja p l = n. Sen sijaan näiden neliöjuurten laskeminen on yleisesti huomattavasti hankalampaa. Erikoistapauksessa p 3 (mod 4) tilanne on toinen. Esimerkki 7.3. Olkoon p 3 (mod 4) ja x QR p. Silloin (±x p+1 4 ) 2 x p+1 2 x x p 1 2 x (mod p). Siten luvut ±x p+1 4 ovat x:n neliöjuuret. Tässä tapauksessa neliöjuuret voidaan siis määrätä kuutiollisessa ajassa. Jatkossa tarkastellaan tapausta p 1 (mod 4), mikä on selvästi hankalampi. Olkoon x QR p, jolloin siis x on olemassa modulo p. Vaikka x olisikin tuntematon, kahden luvun a + b x ja c + d x tulo modulo p voidaan laskea symbolisesti kaavalla (a + b x)(c + d x) ac + ad x + bc x + bd( x) 2 (ac + bdx) + (ad + bc) x (mod p), jolloin tulokin saadaan samassa muodossa. Ja koska tulo voidaan laskea, onnistuu myös luvun a + b x potenssien laskeminen: (a + b x) n α + β x (mod p). Potenssi voidaan laskea peräkkäisten neliöiden menetelmällä, ja laskun kompleksisuus on kuutiollinen (O(n) symbolista tuloa, joista kukin onnistuu ajassa O(n 2 ).) Esitetään neliöjuuren laskeva algoritmi, jonka jälkeen perustellaan sen toimivuus. Algoritmi 7.5. LValgoritmi LVSqrt x:lle modulo alkuluku. syöte: moduli p 1 (mod 4), x QR p, yritysten määrä k tuloste: x (mod p) i 0, x? repeat i i + 1, a r Z p if a 2 x (mod p) then x min{a, p a} laske c, d: (a + x) p 1 2 c + d x (mod p) if c = 0 ja d 0 then y d 1 (mod p) ( )
67 7.5 Las Vegas -algoritmit 65 x min{y, p y} until i = k tai x? if x? then return x else return ei onnistunut ( ) On helppo tarkistaa, että antaessaan vastauksen algoritmi toimii oikein. Kohta ( ) on selvä, ja kohdassa ( ) on päädytty yhtälöön (a + x) p 1 2 d x (mod p). Kongruenssin vasen puoli on aina ±1, joten joko x = d 1 (mod p) tai x = d 1 (mod p). Jäljelle jää algoritmin onnistumistodennäköisyyden arviointi. Tarkastellaan, millä todennäköisyydellä x löytyy yhdellä a:n satunnaisella valinnalla. Vastaus saadaan todistamalla kaksi seuraavaa lemmaa. Lemma 7.3. Algoritmissa LVSqrt: [c = 0 ja d 0] a 2 x QNR p. Todistus. Jos a 2 x QNR p, niin (a + x) p 1 2 (a x) p 1 2 (a 2 x) p (mod p). Siispä välttämättä (a + x) p 1 2 ε ja (a x) p 1 2 ε, missä ε ±1. Toisaalta, koska (a + x) p 1 2 c + d x (mod p), on välttämättä (a p 1 x) 2 c d x (mod p). Saadaan yhtälöpari c + d x ε c d (mod p). x ε Tästä saadaan 2c 0 (mod p), joten c = 0 ja d 0. Toiseen suuntaan, jos a 2 x QR p, niin aivan vastaavasti (a+ x) p 1 2 (a x) p 1 2 ε. Saadaan 2d x 0 (mod p), joten d = 0. Todistuksesta nähdään, että jos algoritmissa LVSqrt päädytään tilanteeseen d 0, niin välttämättä samalla c = 0. On vielä arvioitava, kuinka monella a:n arvolla 1,..., p 1 luku (a 2 x) ei ole neliönjäännös. Tai yleisemmin, kuinka monella a:n arvolla algoritmi laskee x:n neliöjuuren. Merkitään S x :llä näiden alkioiden joukkoa: S x = {a Z p a 2 x QNR p tai a 2 x 0 (mod p)}. Lemma 7.4. S x = p+3 2.
68 7.5 Las Vegas -algoritmit 66 Todistus. Aluksi todetaan, että ± x S x, joten joukossa on ainakin kaksi alkiota. Jatkossa oletetaan, että a ± x. Määritellään funktio f ehdosta f(a) = a + x a x = (a2 x) ( (a x) 1) 2. Selvästi f(a) on neliön(epä)jäännös tarkalleen silloin, kun a 2 x on neliön(epä)jäännös modulo p. Osoitetaan, että f on bijektio joukolta Z p \ {± x} joukkoon Z p \ {±1}. Koska sekä 1 että 1 ovat neliönjäännöksiä modulo p (sillä p 1 (mod 4)), niin tästä väite jo seuraakin. Ensiksi todetaan, että f(a) ±1. Jos näin ei olisi, f:n määrittelystä seuraisi, että joko a = 0 tai x = 0, mikä on mahdotonta. Toiseksi huomataan, että joukot Z p \ {± x} ja Z p \ {±1} ovat yhtä suuria. Näin ollen jäljelle jää todistaa, että f on injektio. Oletetaan, että f(a) = f(b). Tällöin (a x)f(a) (a + x) (b x)f(a) (b + (a b)f(a) (a b) a b tai f(a) 1. x) Koska f(a) 1 (mod p), on oltava a b (mod p), joten f on injektio. Yhdellä satunnaisella a:n valinnalla algoritmi LVSqrt tuottaa vastauksen todennäköisyydellä S x / Z p = p+3 2p Kun kierroksia on k kpl, on onnistumisen todennäköisyys vähintään 1 ( 1 2 )k. Todetaan vielä, että algoritmin yhden kierroksen kompleksisuus on maksimissaan kuutiollinen, sillä sekä käänteisalkion laskeminen modulo p että potenssin (a + x) p 1 2 laskeminen onnistuu tässä ajassa. Seuraava lause on siis todistettu. Lause 7.5. Luvun x neliöjuuri modulo p voidaan laskea LV-algoritmilla ajassa O(kn 3 ), jolloin virhetodennäköisyys on korkeintaan ( 1 2 )k.
69 8.6 Jaollisuudesta i Liite: Kokonaisluvuista 8.6 Jaollisuudesta Määritelmä 8.1. Olkoot a ja b kokonaislukuja ja a 0. Sanotaan, että a jakaa luvun b (tai b on jaollinen luvulla a tai a on luvun b tekijä), jos on olemassa sellainen kokonaisluku k, että b = ka. Tällöin merkitään a b. Jos a ei jaa lukua b, merkitään a b. Lause ) Jos a b ja a c, niin a (b + c). 2) Jos a b, niin myös a bc kaikille c Z. 3) Jos a b ja b c, niin a c. Määritelmä 8.2. Kokonaislukua p 2 sanotaan alkuluvuksi, jos sen ainoat positiiviset tekijät ovat 1 ja p. Jos n 2 ei ole alkuluku, se on yhdistetty luku. Esimerkki 8.4. Luku 1 ei ole alkuluku. Pienimmät alkuluvut ovat 2, 3, 5, 7, 11, 13, 17, 19, 23,... Lause 8.7 (Aritmetiikan peruslause). Jokainen positiivinen kokonaisluku n 2 voidaan kirjoittaa alkulukujen tulona. Tällainen esitys on tekijöiden järjestystä lukuunottamatta yksikäsitteinen. Todistus. Luku 2 on alkulukujen tulo. Oletetaan, että jokainen lukua n pienempi luku voidaan esittää alkulukujen tulona. Jos n ei ole alkuluku, niin on olemassa sellaiset kokonaislukutekijät n 1 ja n 2, että 1 < n 1 < n, 1 < n 2 < n ja n = n 1 n 2. Induktio-oletuksen nojalla sekä n 1 että n 2 voidaan esittää alkulukujen tulona, näin myös n. Yksikäsitteisyyspuolen todistus suoritetaan myöhemmin. Lause 8.8. Alkulukuja on äärettömän paljon. Todistus. Oletetaan, että p 1,..., p k ovat ainoat alkuluvut ja tarkastellaan lukua n = 1+p 1... p k. Luku n voidaan kirjoittaa alkulukujen tulona. Olkoon p jokin luvun n alkutekijöistä. Jos muita alkulukuja kuin p 1,..., p k ei ole olemassa, niin p on niistä jokin, sanotaan p = p i. Tällöin p jakaa luvun n p 1... p k = 1, mikä on ristiriita. Lause 8.9. Jos n on yhdistetty luku, niin luvulla n on alkulukutekijä, joka on suuruudeltaan enintään n. Todistus. Koska n on yhdistetty luku, on olemassa sellaiset kokonaisluvut a ja b, että n = ab, missä 1 < a < n ja 1 < b < n. Välttämättä a n tai b n, muutenhan ab > n n = n. Jos esim. a n, niin mikä tahansa luvun a alkulukutekijä p on myös luvun n tekijä ja p n.
70 8.6 Jaollisuudesta ii Jos x R, merkitään Selvästi x = { suurin kokonaisluku x}. x 1 < x x. (6) Lause Olkoon a kokonaisluku ja d positiivinen kokonaisluku. Silloin on olemassa yksikäsitteiset sellaiset kokonaisluvut q ja r, että a = dq + r, 0 r < d. Todistus. Valitaan q = a/d, r = a dq. Väite on voimassa, koska kaavan (6) nojalla 0 = a d a d r = a dq < a d(a 1) = d, d ts. 0 r < d. Jos myös q ja r toteuttaisivat ehdot a = dq + r ja 0 r < d, niin dq + r = dq + r ja siis d(q q ) = r r. Näin luku r r on jaollinen luvulla d ja toisaalta d < r r < d, joten r r = 0, ts. r = r. Tällöin välttämättä myös q = q. Määritelmä 8.3. Olkoot a ja b kokonaislukuja, jotka eivät molemmat ole nollia. Jos d on sellainen positiivinen kokonaisluku, että d a ja d b ja aina, jos c a ja c b, niin myös c d, niin lukua d kutsutaan lukujen a ja b suurimmaksi yhteiseksi tekijäksi. Jos tällainen luku on olemassa, niin se on selvästi yksikäsitteinen ja sille käytetään merkintää syt(a, b). Seuraava lause osoittaa, että syt(a, b) on aina olemassa ja antaa nopean algoritmin sen löytämiseksi. Lause 8.11 (Eukleideen algoritmi). Kokonaislukujen a ja b 0 suurin yhteinen tekijä voidaan aina laskea soveltamalla lausetta 8.10 toistuvasti: a = q 1 b + r 1, 0 < r 1 < b, b = q 2 r 1 + r 2, 0 < r 2 < r 1, r 1 = q 3 r 2 + r 3, 0 < r 3 < r 2,. r n 2 = q n r n 1 + r n, 0 < r n < r n 1, r n 1 = q n+1 r n..
71 8.6 Jaollisuudesta iii Prosessi päättyy, koska r 1 > r 2 > r 3 >... ja luvut r i ovat ei-negatiivisia kokonaislukuja. Tällöin syt(a, b) = r n = viimeisen jakolaskun jakaja. Lisäksi tällä menetelmällä löydetään aina sellaiset kokonaisluvut u ja v, että ua + vb = syt(a, b). Todistus. Kulkemalla yhtälöketjussa alhaalta ylöspäin todetaan, että r n r n 1, r n q n r n 1 + r n = r n 2,..., r n b, r n a. Kulkemalla ylhäältä alaspäin todetaan, että c a, c b, c r 1,..., c r n. Siis r n = syt(a, b). Lisäksi kulkemalla taas alhaalta ylöspäin saadaan r n = r n 2 q n r n 1 = r n 2 q n (r n 3 q n 1 r n 2 ) = q n r n 3 + (1 + q n 1 q n )r n 2... = ua + vb, joka on vaadittu kokonaislukuesitys suurimmalle yhteiselle tekijälle. Lause Jos p on alkuluku ja p ab, niin p a tai p b. Todistus. Jos p a, niin syt(a, p) = 1 koska p on alkuluku. Edellisen lauseen nojalla on siis olemassa sellaiset kokonaisluvut s ja t, että 1 = sa + tp. Kertomalla tämä puolittain luvulla b saadaan b = sab + tpb, mistä nähdään, että p b. Aritmetiikan peruslauseen todistuksen loppuosa. Oletetaan, että n = n 1... n k = m 1... m h. Jos tässä k = 1, niin n = n 1 on alkuluku, joka jakaa oikean puolen. Äskeisen lauseen (tai oikeastaan sen induktiivisen yleistyksen) nojalla n jakaa jonkin luvuista m i, sanotaan luvun m 1, jolloin tietysti n = m 1, koska molemmat ovat alkulukuja. Mutta tällöin m 2... m h = 1, mikä on mahdotonta, ellei itse asiassa ollut juuri h = 1, n 1 = m 1. Oletetaan induktiivisesti, että tiedetään, että em. kahden esityksen täytyy olla samoja, jos k < t, ja oletetaan, että k = t. Sama argumentti kuin edellä osoittaa, että n 1 on jokin luvuista m i, sanotaan m 1, ja silloin n 2... n k = m 2... m h, ja väite seuraa induktio-oletuksesta.
72 8.7 Kongruenssi ja jäännösluokat modulo n iv 8.7 Kongruenssi ja jäännösluokat modulo n Jos a on kokonaisluku ja n positiivinen kokonaisluku, niin lauseen 8.10 nojalla on olemassa yksikäsitteiset kokonaisluvut q ja r, joille a = qn + r, 0 r < n. Lukua r sanotaan luvun a jäännökseksi modulo n. Selvästi kahdella luvulla on sama jäännös modulo n tarkalleen silloin, kun niiden erotus on jaollinen luvulla n. Seuraavan määritelmän avulla useat jaollisuustarkastelut voidaan muuttaa muotoon, joka on monessa suhteessa analoginen yhtälöiden ja yhtälöryhmien teorian kanssa. Määritelmä 8.4. Oletetaan, että n on positiivinen kokonaisluku ja a, b Z. Jos n a b, sanotaan että a on kongruentti luvun b kanssa modulo n ja merkitään a b (mod n). Esimerkki (mod 9), 5 1 (mod 3), a b (mod 2) jos ja vain jos a ja b ovat molemmat parillisia tai molemmat parittomia. Lause ) Jokainen kokonaisluku on kongruentti tarkalleen yhden luvuista 0, 1,..., n 1 kanssa modulo n. 2) Aina a a (mod n). 3) Jos a b (mod n), niin b a (mod n). 4) Jos a b (mod n) ja b c (mod n), niin myös a c (mod n). 5) Jos a b (mod n) ja c d (mod n), niin ja a + c b + d (mod n) ac bd (mod n). 6) Jos ca cb (mod n) ja lisäksi syt(c, n) = 1, niin a b (mod n). Todistus. Kohdat 1), 2) ja 3) ovat selviä lauseen 8.10 nojalla, kohta 4) ja kohdan 5) ensimmäinen väite helppoja. Kohdan 5) jälkimmäinen väite nähdään seuraavasti. Koska a b (mod n), niin n a b ja tietysti myös n c(a b), joten ac bc (mod n) siis kongruessin molemmat puolet saa kertoa samalla kokonaisluvulla. Näin ollen myös bc bd (mod n) ja siis ac bc bd (mod n) kohdan 4) nojalla. Todistetaan vielä kohta 6). Lauseen 8.11 nojalla koska syt(c, n) = 1 on olemassa sellaiset kokonaisluvut u ja v, että uc + vn = 1. Näin ollen n uc(a b) + vn(a b) = a b.
73 8.7 Kongruenssi ja jäännösluokat modulo n v Soveltamalla kohdan 6) jälkimmäistä väitettä useita kertoja peräkkäin todetaan, että ehdosta a b (mod n) seuraa, että a k b k (mod n) kaikilla positiivisilla kokonaisluvuilla k. Esimerkki 8.6. Selvitetään, mikä on jakojäännös, kun luku jaetaan luvulla 7. On siis selvitettävä, minkä luvuista 0, 1,..., 6 kanssa luku on kongruentti modulo 7. Koska 12 5 (mod 7), on (mod 7). Edelleen = (5 2 ) 60 = ja 25 4 (mod 7), joten Samalla tavalla jatkamalla todetaan, että ja siis Kysytty jakojäännös on siis = = 1 (mod 7) = 2 (mod 7). Määritelmä 8.5. Olkoon a jokin kokonaisluku. Luvun a määräämällä jäännösluokalla modulo n tarkoitetaan joukkoa {x Z x a (mod n)}. Tätä merkitään myös symbolilla a (jolloin luku n ajatellaan tunnetuksi). Aina a a. Esimerkki 8.7. Jos n = 5, niin 2 = {x Z x 2 (mod 5)} = {..., 8, 3, 2, 7, 12, 17,...} = {2 + 5k k Z}. Lause Oletetaan, että n on kiinnitetty. 1) a = b a b (mod n) n a b. 2) Jos a = a ja b = b, niin a + b = a + b ja ab = a b. 3) Kaikki jäännösluokat modulo n ovat 0,..., n 1. Todistus. 1) Jos a = b, niin a a = b, joten a b (mod n). Kääntäen, jos a b (mod n), nin x a x a (mod n) x b (mod n) x b. 2) Koska a = a ja b = b, niin kohdan 1) nojalla a a (mod n) ja b b (mod n). Lauseen 8.13 kohdan 5) nojalla a+b a +b (mod n) ja ab a b (mod n) ja jälleen kohdan 1) nojalla a + b = a + b ja ab = a b. 3) Jäännösluokat 0, 1,..., n 1 ovat kaikki eri joukkoja kohdan 1) nojalla; muita ei ole lauseen 8.13 kohdan 1) nojalla.
74 8.7 Kongruenssi ja jäännösluokat modulo n vi Vaikka 0,..., n 1 ovat kaikki jäännösluokat modulo n, niin samasta jäännösluokasta voidaan tietysti käyttää useita eri nimiä. Esim. jos n = 5, niin 2 = 7 = 3. Määritelmä 8.6. Joukolle, jonka alkioina ovat kaikki jäännösluokat modulo n, käytetään merkintää Z n : Z n = {0, 1,..., n 1}. Joukossa Z n voidaan edellisen lauseen kohdan 2) perusteella määritellä yhteenja kertolasku asettamalla a + b = a + b ja a b = ab. Näin Z n on oikeastaan joukoista koostuva joukko. Ääretön joukko Z on jaettu äärellisen moneen palaan 0,..., n 1. Esimerkki 8.8. missä ja Z 2 = {0, 1}, 0 = {..., 2, 0, 2, 4,...} = {parilliset luvut} 1 = {..., 3, 1, 1, 3,...} = {parittomat luvut}. Esimerkiksi = = 0, = = 0, 1 1 = 1 1 = 1. Esimerkki 8.9. missä Z 3 = {0, 1, 2}, 0 = {..., 3, 0, 3, 6,...} 1 = {..., 2, 1, 4, 7,...} 2 = {..., 1, 2, 5, 8,...}. Esimerkiksi = 3 = 0 ja 2 2 = 2 2 = 4 = 1. Esimerkki Etsittävä kaikki kokonaisluvut x, joille x 2 1 (mod 8). Jos luku x toteuttaa tämän kongruenssin, niin lauseen 8.13 laskusääntöjen nojalla myös jokainen luvun x kanssa kongruentti luku toteuttaa sen. Riittää siis kokeilla lukuja 0, 1,..., 7 ja katsoa, mitkä niistä toteuttavat ko. kongruenssin. Laskemalla todetaan, että kongruenssi on näistä voimassa luvuille 1, 3, 5 ja 7. Näin x 2 1 (mod 8) jos ja vain jos x 1, 3, 5 tai 7 (mod 8), ts. tarkalleen silloin kun x on pariton.
75 8.7 Kongruenssi ja jäännösluokat modulo n vii Todistetaan lopuksi ns. Fermat'n pieni lause, jota tarvitaan RSA-salausmenetelmän perusteluissa. Lause 8.15 (Fermat'n pieni lause). Jos p on alkuluku ja a Z ei ole jaollinen luvulla p, niin a p 1 1 (mod p). Todistus. Kaikki jäännösluokat modulo p ovat 0, 1,..., p 1. Mutta jos a 0 (eli a ei ole jaollinen p:llä), niin myös 0a, 1a, 2a,..., (p 1)a ovat kaikki jäännösluokat modulo p, sillä niitä on p kappaletta ja ia ja kaikilla i, j {0, 1, 2,..., p 1}. Siis kummassakin listassa on samat alkiot jossakin järjestyksessä, joten eli a 2a... (p 1)a = p 1 a 2a... (p 1)a (p 1) (mod p). Jakamalla puolittain luvulla (p 1)! mikä lauseen 8.13 kohdan 6) nojalla luvallista saadaan a p 1 1 (mod p).
Algoritminen matematiikka
Algoritminen matematiikka Luentomoniste Turun yliopisto Matematiikan laitos 20014 Turku 2016 i Alkusanat Kurssin tarkoituksena on algoritmisen ajattelun omaksuminen ja kehittäminen. Tavanomaisesti matematiikassa
1 Lukujen jaollisuudesta
Matematiikan mestariluokka, syksy 2009 1 1 Lukujen jaollisuudesta Lukujoukoille käytetään seuraavia merkintöjä: N = {1, 2, 3, 4,... } Luonnolliset luvut Z = {..., 2, 1, 0, 1, 2,... } Kokonaisluvut Kun
Lukuteorian kertausta
Lukuteorian kertausta Jakoalgoritmi Jos a, b Z ja b 0, niin on olemassa sellaiset yksikäsitteiset kokonaisluvut q ja r, että a = qb+r, missä 0 r < b. Esimerkki 1: Jos a = 60 ja b = 11, niin 60 = 5 11 +
f(n) = Ω(g(n)) jos ja vain jos g(n) = O(f(n))
Määritelmä: on O(g(n)), jos on olemassa vakioarvot n 0 > 0 ja c > 0 siten, että c g(n) kun n > n 0 O eli iso-o tai ordo ilmaisee asymptoottisen ylärajan resurssivaatimusten kasvun suuruusluokalle Samankaltaisia
811120P Diskreetit rakenteet
811120P Diskreetit rakenteet 2016-2017 2. Lukujen esittäminen ja aritmetiikka 2.1 Kantajärjestelmät ja lukujen esittäminen Käytettävät lukujoukot: Luonnolliset luvut IN = {0,1,2,3,... } Positiiviset kokonaisluvut
LUKUTEORIA johdantoa
LUKUTEORIA johdantoa LUKUTEORIA JA TODISTAMINEN, MAA11 Lukuteorian tehtävä: Lukuteoria tutkii kokonaislukuja, niiden ominaisuuksia ja niiden välisiä suhteita. Kokonaislukujen maailma näyttää yksinkertaiselta,
Algoritmit 1. Luento 2 Ke Timo Männikkö
Algoritmit 1 Luento 2 Ke 11.1.2017 Timo Männikkö Luento 2 Algoritmin esitys Algoritmien analysointi Suoritusaika Asymptoottinen kertaluokka Peruskertaluokkia NP-täydelliset ongelmat Algoritmit 1 Kevät
Nopea kertolasku, Karatsuban algoritmi
Nopea kertolasku, Karatsuban algoritmi Mikko Männikkö 16.8.2004 Lähde: ((Gathen and Gerhard 1999) luku II.8) Esityksen kulku Algoritmien analysointia (1), (2), (3), (4) Klassinen kertolasku Parempi tapa
Tekijä Pitkä Matematiikka 11 ratkaisut luku 2
Tekijä Pitkä matematiikka 11 0..017 170 a) Koska 8 = 4 7, luku 8 on jaollinen luvulla 4. b) Koska 104 = 4 6, luku 104 on jaollinen luvulla 4. c) Koska 4 0 = 80 < 8 ja 4 1 = 84 > 8, luku 8 ei ole jaollinen
2.1. Tehtävänä on osoittaa induktiolla, että kaikille n N pätee n = 1 n(n + 1). (1)
Approbatur 3, demo, ratkaisut Sovitaan, että 0 ei ole luonnollinen luku. Tällöin oletusta n 0 ei tarvitse toistaa alla olevissa ratkaisuissa. Se, pidetäänkö nollaa luonnollisena lukuna vai ei, vaihtelee
Johdatus lukuteoriaan Harjoitus 2 syksy 2008 Eemeli Blåsten. Ratkaisuehdotelma
Johdatus lukuteoriaan Harjoitus 2 syksy 2008 Eemeli Blåsten Ratkaisuehdotelma Tehtävä 1 1. Etsi lukujen 4655 ja 12075 suurin yhteinen tekijä ja lausu se kyseisten lukujen lineaarikombinaationa ilman laskimen
R : renkaan R kääntyvien alkioiden joukko; R kertolaskulla varustettuna on
0. Kertausta ja täydennystä Kurssille Äärelliset kunnat tarvittavat esitiedot löytyvät Algebran kurssista [Alg]. Hyödyksi voivat myös olla (vaikka eivät välttämättömiä) Lukuteorian alkeet [LTA] ja Salakirjoitukset
3. Kongruenssit. 3.1 Jakojäännös ja kongruenssi
3. Kongruenssit 3.1 Jakojäännös ja kongruenssi Tässä kappaleessa esitellään kokonaislukujen modulaarinen aritmetiikka (ns. kellotauluaritmetiikka), jossa luvut tyypillisesti korvataan niillä jakojäännöksillä,
Diskreetin matematiikan perusteet Laskuharjoitus 2 / vko 9
Diskreetin matematiikan perusteet Laskuharjoitus 2 / vko 9 Tuntitehtävät 9-10 lasketaan alkuviikon harjoituksissa ja tuntitehtävät 13-14 loppuviikon harjoituksissa. Kotitehtävät 11-12 tarkastetaan loppuviikon
on Abelin ryhmä kertolaskun suhteen. Tämän joukon alkioiden lukumäärää merkitään
5. Primitiivinen alkio 5.1. Täydennystä lukuteoriaan. Olkoon n Z, n 2. Palautettakoon mieleen, että kokonaislukujen jäännösluokkarenkaan kääntyvien alkioiden muodostama osajoukko Z n := {x Z n x on kääntyvä}
802328A LUKUTEORIAN PERUSTEET OSA III BASICS OF NUMBER THEORY PART III. Tapani Matala-aho MATEMATIIKKA/LUTK/OULUN YLIOPISTO
8038A LUKUTEORIAN PERUSTEET OSA III BASICS OF NUMBER THEORY PART III Tapani Matala-aho MATEMATIIKKA/LUTK/OULUN YLIOPISTO SYKSY 016 Sisältö 1 Irrationaaliluvuista Antiikin lukuja 6.1 Kolmio- neliö- ja tetraedriluvut...................
MS-A0402 Diskreetin matematiikan perusteet
MS-A0402 Diskreetin matematiikan perusteet Osa 4: Modulaariaritmetiikka Riikka Kangaslampi 2017 Matematiikan ja systeemianalyysin laitos Aalto-yliopisto Modulaariaritmetiikka Jakoyhtälö Määritelmä 1 Luku
802328A LUKUTEORIAN PERUSTEET OSA III BASICS OF NUMBER THEORY PART III
802328A LUKUTEORIAN PERUSTEET OSA III BASICS OF NUMBER THEORY PART III Tapani Matala-aho MATEMATIIKKA/LUTK/OULUN YLIOPISTO SYKSY 2016 LUKUTEORIA 1 / 77 Irrationaaliluvuista Määritelmä 1 Luku α C \ Q on
Salausmenetelmät. Veikko Keränen, Jouko Teeriaho (RAMK, 2006)
Salausmenetelmät Veikko Keränen, Jouko Teeriaho (RAMK, 2006) LUKUTEORIAA JA ALGORITMEJA 3. Kongruenssit à 3.1 Jakojäännös ja kongruenssi Määritelmä 3.1 Kaksi lukua a ja b ovat keskenään kongruentteja (tai
Matematiikan mestariluokka, syksy 2009 7
Matematiikan mestariluokka, syksy 2009 7 2 Alkuluvuista 2.1 Alkuluvut Määritelmä 2.1 Positiivinen luku a 2 on alkuluku, jos sen ainoat positiiviset tekijät ovat 1 ja a. Jos a 2 ei ole alkuluku, se on yhdistetty
Tietorakenteet ja algoritmit - syksy 2015 1
Tietorakenteet ja algoritmit - syksy 2015 1 Tietorakenteet ja algoritmit - syksy 2015 2 Tietorakenteet ja algoritmit Johdanto Ari Korhonen Tietorakenteet ja algoritmit - syksy 2015 1. JOHDANTO 1.1 Määritelmiä
a b 1 c b n c n
Algebra Syksy 2007 Harjoitukset 1. Olkoon a Z. Totea, että aina a 0, 1 a, a a ja a a. 2. Olkoot a, b, c, d Z. Todista implikaatiot: a) a b ja c d ac bd, b) a b ja b c a c. 3. Olkoon a b i kaikilla i =
Johdatus diskreettiin matematiikkaan Harjoitus 5, Ratkaise rekursioyhtälö
Johdatus diskreettiin matematiikkaan Harjoitus 5, 14.10.2015 1. Ratkaise rekursioyhtälö x n+4 2x n+2 + x n 16( 1) n, n N, alkuarvoilla x 1 2, x 2 14, x 3 18 ja x 4 42. Ratkaisu. Vastaavan homogeenisen
58131 Tietorakenteet ja algoritmit (syksy 2015)
58131 Tietorakenteet ja algoritmit (syksy 2015) Harjoitus 2 (14. 18.9.2015) Huom. Sinun on tehtävä vähintään kaksi tehtävää, jotta voit jatkaa kurssilla. 1. Erään algoritmin suoritus vie 1 ms, kun syötteen
2. Eukleideen algoritmi
2. Eukleideen algoritmi 2.1 Suurimman yhteisen tekijän tehokas laskutapa Tässä luvussa tarkastellaan annettujen lukujen suurimman yhteisen tekijän etsimistä tehokkaalla tavalla. Erinomaisen käyttökelpoinen
811120P Diskreetit rakenteet
811120P Diskreetit rakenteet 2016-2017 6. Alkeislukuteoria 6.1 Jaollisuus Käsitellään kokonaislukujen perusominaisuuksia: erityisesti jaollisuutta Käytettävät lukujoukot: Luonnolliset luvut IN = {0,1,2,3,...
Algoritmit 2. Luento 8 To Timo Männikkö
Algoritmit 2 Luento 8 To 4.4.2019 Timo Männikkö Luento 8 Algoritmien analysointi Algoritmien suunnittelu Rekursio Osittaminen Rekursioyhtälöt Rekursioyhtälön ratkaiseminen Master-lause Algoritmit 2 Kevät
1.4 Funktioiden kertaluokat
1.4 Funktioiden kertaluokat f on kertaluokkaa O(g), merk. f = O(g), jos joillain c > 0, m N pätee f(n) cg(n) aina kun n m f on samaa kertaluokkaa kuin g, merk. f = Θ(g), jos joillain a, b > 0, m N pätee
JOHDATUS LUKUTEORIAAN (syksy 2017) HARJOITUS 3, MALLIRATKAISUT
JOHDATUS LUKUTEORIAAN (syksy 2017) HARJOITUS 3, MALLIRATKAISUT Tehtävä 1. (i) Olkoot n, d 1 ja d n. Osoita, että (k, n) d jos ja vain jos k ad, missä (a, n/d) 1. (ii) Osoita, että jos (m j, m k ) 1 kun
Matematiikan ja tilastotieteen laitos Algebra I - Kesä 2009 Ratkaisuehdoituksia harjoituksiin 8 -Tehtävät 3-6 4 sivua Heikki Koivupalo ja Rami Luisto
Matematiikan ja tilastotieteen laitos Algebra I - Kesä 2009 Ratkaisuehdoituksia harjoituksiin 8 -Tehtävät 3-6 4 sivua Heikki Koivupalo ja Rami Luisto 3. Oletetaan, että kunnan K karakteristika on 3. Tutki,
Algoritmit 1. Demot Timo Männikkö
Algoritmit 1 Demot 1 31.1.-1.2.2018 Timo Männikkö Tehtävä 1 (a) Algoritmi, joka tutkii onko kokonaisluku tasan jaollinen jollain toisella kokonaisluvulla siten, että ei käytetä lainkaan jakolaskuja Jaettava
Matematiikan tukikurssi, kurssikerta 3
Matematiikan tukikurssi, kurssikerta 3 1 Epäyhtälöitä Aivan aluksi lienee syytä esittää luvun itseisarvon määritelmä: { x kun x 0 x = x kun x < 0 Siispä esimerkiksi 10 = 10 ja 10 = 10. Seuraavaksi listaus
Algoritmit 2. Luento 1 Ti Timo Männikkö
Algoritmit 2 Luento 1 Ti 14.3.2017 Timo Männikkö Luento 1 Algoritmi Algoritmin valinta Algoritmin analysointi Algoritmin suoritusaika Peruskertaluokkia Kertaluokkamerkinnät Kertaluokkien ominaisuuksia
Algebra I, harjoitus 5,
Algebra I, harjoitus 5, 7.-8.10.2014. 1. 2 Osoita väitteet oikeiksi tai vääriksi. a) (R, ) on ryhmä, kun asetetaan a b = 2(a + b) aina, kun a, b R. (Tässä + on reaalilukujen tavallinen yhteenlasku.) b)
a ord 13 (a)
JOHDATUS LUKUTEORIAAN (syksy 2017) HARJOITUS 4, MALLIRATKAISUT Tehtävä 1. Etsi asteet ord p (a) luvuille a 1, 2,..., p 1 kun p = 13 ja kun p = 17. (ii) Mitkä jäännösluokat ovat primitiivisiä juuria (mod
Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen
Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari 1 1. JOHDANTO 1.1 Määritelmiä 1.2 Tietorakenteen ja algoritmin valinta 1.3 Algoritmit ja tiedon määrä 1.4 Tietorakenteet ja toiminnot 1.5 Esimerkki:
7. Olemassaolo ja yksikäsitteisyys Galois n kunta GF(q) = F q, jossa on q alkiota, määriteltiin jäännösluokkarenkaaksi
7. Olemassaolo ja yksikäsitteisyys Galois n kunta GF(q) = F q, jossa on q alkiota, määriteltiin jäännösluokkarenkaaksi Z p [x]/(m), missä m on polynomirenkaan Z p [x] jaoton polynomi (ks. määritelmä 3.19).
2 j =
1. Modulaariaritmetiikkaa Yksinkertaisissa salausjärjestelmissä käytettävä matematiikka on paljolti lukuteoriaan pohjautuvaa suurten lukujen modulaariaritmetiikkaa (lasketaan kokonaisluvuilla modulo n).
Jokaisen parittoman kokonaisluvun toinen potenssi on pariton.
3 Todistustekniikkaa 3.1 Väitteen kumoaminen vastaesimerkillä Monissa tilanteissa kohdataan väitteitä, jotka koskevat esimerkiksi kaikkia kokonaislukuja, kaikkia reaalilukuja tai kaikkia joukkoja. Esimerkkejä
811120P Diskreetit rakenteet
811120P Diskreetit rakenteet 2016-2017 ari.vesanen (at) oulu.fi 5. Rekursio ja induktio Rekursio tarkoittaa jonkin asian määrittelyä itseensä viittaamalla Tietojenkäsittelyssä algoritmin määrittely niin,
811120P Diskreetit rakenteet
811120P Diskreetit rakenteet 2016-2017 1. Algoritmeista 1.1 Algoritmin käsite Algoritmi keskeinen laskennassa Määrittelee prosessin, joka suorittaa annetun tehtävän Esimerkiksi Nimien järjestäminen aakkosjärjestykseen
Liite 1. Laajennettu Eukleideen algoritmi suoraviivainen tapa
Liite 1. Laajennettu Eukleideen algoritmi suoraviivainen tapa - johdanto - matemaattinen induktiotodistus - matriisien kertolaskun käyttömahdollisuus - käsinlaskuesimerkkejä - kaikki välivaiheet esittävä
Esko Turunen Luku 3. Ryhmät
3. Ryhmät Monoidia rikkaampi algebrallinen struktuuri on ryhmä: Määritelmä (3.1) Olkoon joukon G laskutoimitus. Joukko G varustettuna tällä laskutoimituksella on ryhmä, jos laskutoimitus on assosiatiivinen,
811120P Diskreetit rakenteet
811120P Diskreetit rakenteet 2018-2019 1. Algoritmeista 1.1 Algoritmin käsite Algoritmi keskeinen laskennassa Määrittelee prosessin, joka suorittaa annetun tehtävän Esimerkiksi Nimien järjestäminen aakkosjärjestykseen
Cantorin joukon suoristuvuus tasossa
Cantorin joukon suoristuvuus tasossa LuK-tutkielma Miika Savolainen 2380207 Matemaattisten tieteiden laitos Oulun yliopisto Syksy 2016 Sisältö Johdanto 2 1 Cantorin joukon esittely 2 2 Suoristuvuus ja
a k+1 = 2a k + 1 = 2(2 k 1) + 1 = 2 k+1 1. xxxxxx xxxxxx xxxxxx xxxxxx
x x x x x x x x Matematiikan johdantokurssi, syksy 08 Harjoitus, ratkaisuista Hanoin tornit -ongelma: Tarkastellaan kolmea pylvästä A, B ja C, joihin voidaan pinota erikokoisia renkaita Lähtötilanteessa
rm + sn = d. Siispä Proposition 9.5(4) nojalla e d.
9. Renkaat Z ja Z/qZ Tarkastelemme tässä luvussa jaollisuutta kokonaislukujen renkaassa Z ja todistamme tuloksia, joita käytetään jäännösluokkarenkaan Z/qZ ominaisuuksien tarkastelussa. Jos a, b, c Z ovat
(iv) Ratkaisu 1. Sovelletaan Eukleideen algoritmia osoittajaan ja nimittäjään. (i) 7 = , 7 6 = = =
JOHDATUS LUKUTEORIAAN (syksy 07) HARJOITUS 7, MALLIRATKAISUT Tehtävä Etsi seuraavien rationaalilukujen ketjumurtokehitelmät: (i) 7 6 (ii) 4 7 (iii) 65 74 (iv) 63 74 Ratkaisu Sovelletaan Eukleideen algoritmia
Lukuteoria. Eukleides Aleksandrialainen (n. 300 eaa)
Lukuteoria Lukuteoria on eräs vanhimmista matematiikan aloista. On sanottu, että siinä missä matematiikka on tieteiden kuningatar, on lukuteoria matematiikan kuningatar. Perehdymme seuraavassa luonnollisten
2017 = = = = = = 26 1
JOHDATUS LUKUTEORIAAN (syksy 2017) HARJOITUS 2, MALLIRATKAISUT Tehtävä 1. Sovella Eukleiden algoritmia ja (i) etsi s.y.t(2017, 753) (ii) etsi kaikki kokonaislukuratkaisut yhtälölle 405x + 141y = 12. Ratkaisu
Algoritmit 1. Luento 11 Ti Timo Männikkö
Algoritmit 1 Luento 11 Ti 14.2.2017 Timo Männikkö Luento 11 Algoritminen ongelmanratkaisu Osittaminen Lomituslajittelu Lomituslajittelun vaativuus Rekursioyhtälöt Pikalajittelu Algoritmit 1 Kevät 2017
811312A Tietorakenteet ja algoritmit Kertausta kurssin alkuosasta
811312A Tietorakenteet ja algoritmit 2017-2018 Kertausta kurssin alkuosasta II Perustietorakenteet Pino, jono ja listat tunnettava Osattava soveltaa rakenteita algoritmeissa Osattava päätellä operaatioiden
2.2 Neliöjuuri ja sitä koskevat laskusäännöt
. Neliöjuuri ja sitä koskevat laskusäännöt MÄÄRITELMÄ 3: Lukua b sanotaan luvun a neliöjuureksi, merkitään a b, jos b täyttää kaksi ehtoa: 1o b > 0 o b a Esim.1 Määritä a) 64 b) 0 c) 36 a) Luvun 64 neliöjuuri
Salakirjoitusmenetelmiä
Salakirjoitusmenetelmiä LUKUTEORIA JA LOGIIKKA, MAA 11 Salakirjoitusten historia on tuhansia vuosia pitkä. On ollut tarve lähettää viestejä, joiden sisältö ei asianomaisen mielestä saanut tulla ulkopuolisten
LUKUTEORIA A. Harjoitustehtäviä, kevät 2013. (c) Osoita, että jos. niin. a c ja b c ja a b, niin. niin. (e) Osoita, että
LUKUTEORIA A Harjoitustehtäviä, kevät 2013 1. Olkoot a, b, c Z, p P ja k, n Z +. (a) Osoita, että jos niin Osoita, että jos niin (c) Osoita, että jos niin (d) Osoita, että (e) Osoita, että a bc ja a c,
Algoritmit 1. Luento 1 Ti Timo Männikkö
Algoritmit 1 Luento 1 Ti 10.1.2017 Timo Männikkö Luento 1 Algoritmi Algoritmin toteutus Ongelman ratkaiseminen Algoritmin tehokkuus Algoritmin suoritusaika Algoritmin analysointi Algoritmit 1 Kevät 2017
Esitetään tehtävälle kaksi hieman erilaista ratkaisua. Ratkaisutapa 1. Lähdetään sieventämään epäyhtälön vasenta puolta:
MATP00 Johdatus matematiikkaan Ylimääräisten tehtävien ratkaisuehdotuksia. Osoita, että 00 002 < 000 000. Esitetään tehtävälle kaksi hieman erilaista ratkaisua. Ratkaisutapa. Lähdetään sieventämään epäyhtälön
A274101 TIETORAKENTEET JA ALGORITMIT
A274101 TIETORAKENTEET JA ALGORITMIT ALGORITMIEN ANALYYSISTÄ 1.ratkaisu Laskentaaika hakkeri - optimoitu ALGORITMIANALYYSIÄ hyvä algoritmi hakkeri -optimoitu hyvä algoritmi Tehtävän koko Kuva mukailtu
Algoritmit 1. Demot Timo Männikkö
Algoritmit 1 Demot 1 25.-26.1.2017 Timo Männikkö Tehtävä 1 (a) Algoritmi, joka laskee kahden kokonaisluvun välisen jakojäännöksen käyttämättä lainkaan jakolaskuja Jaettava m, jakaja n Vähennetään luku
Teema 4. Homomorfismeista Ihanne ja tekijärengas. Teema 4 1 / 32
1 / 32 Esimerkki 4A.1 Esimerkki 4A.2 Esimerkki 4B.1 Esimerkki 4B.2 Esimerkki 4B.3 Esimerkki 4C.1 Esimerkki 4C.2 Esimerkki 4C.3 2 / 32 Esimerkki 4A.1 Esimerkki 4A.1 Esimerkki 4A.2 Esimerkki 4B.1 Esimerkki
A ja B pelaavat sarjan pelejä. Sarjan voittaja on se, joka ensin voittaa n peliä.
Esimerkki otteluvoiton todennäköisyys A ja B pelaavat sarjan pelejä. Sarjan voittaja on se, joka ensin voittaa n peliä. Yksittäisessä pelissä A voittaa todennäköisyydellä p ja B todennäköisyydellä q =
Matematiikan tukikurssi
Matematiikan tukikurssi Kurssikerta 1 1 Matemaattisesta päättelystä Matemaattisen analyysin kurssin (kuten minkä tahansa matematiikan kurssin) seuraamista helpottaa huomattavasti, jos opiskelija ymmärtää
d Z + 17 Viimeksi muutettu
5. Diffien ja Hellmanin avaintenvaihto Miten on mahdollista välittää salatun viestin avaamiseen tarkoitettu avain Internetin kaltaisen avoimen liikennöintiväylän kautta? Kuka tahansahan voi (ainakin periaatteessa)
Tietorakenteet (syksy 2013)
Tietorakenteet (syksy 2013) Harjoitus 1 (6.9.2013) Huom. Sinun on osallistuttava perjantain laskuharjoitustilaisuuteen ja tehtävä vähintään kaksi tehtävää, jotta voit jatkaa kurssilla. Näiden laskuharjoitusten
4. Ryhmien sisäinen rakenne
4. Ryhmien sisäinen rakenne Tässä luvussa tarkastellaan joitakin tapoja päästä käsiksi ryhmien sisäiseen rakenteeseen. Useimmat tuloksista ovat erityisen käyttökelpoisia äärellisten ryhmien tapauksessa.
Johdatus matematiikkaan
Johdatus matematiikkaan Luento 7 Mikko Salo 11.9.2017 Sisältö 1. Funktioista 2. Joukkojen mahtavuus Funktioista Lukiomatematiikassa on käsitelty reaalimuuttujan funktioita (polynomi / trigonometriset /
811312A Tietorakenteet ja algoritmit 2015-2016. I Johdanto
811312A Tietorakenteet ja algoritmit 2015-2016 I Johdanto Sisältö 1. Algoritmeista ja tietorakenteista 2. Algoritmien analyysistä 811312A TRA, Johdanto 2 I.1. Algoritmeista ja tietorakenteista I.1.1. Algoritmien
811312A Tietorakenteet ja algoritmit Kertausta kurssin alkuosasta
811312A Tietorakenteet ja algoritmit 2016-2017 Kertausta kurssin alkuosasta II Algoritmien analyysi: oikeellisuus Algoritmin täydellinen oikeellisuus = Algoritmi päättyy ja tuottaa määritellyn tuloksen
Lineaariset kongruenssiyhtälöryhmät
Lineaariset kongruenssiyhtälöryhmät LuK-tutkielma Jesse Salo 2309369 Matemaattisten tieteiden laitos Oulun yliopisto Sisältö Johdanto 2 1 Kongruensseista 3 1.1 Kongruenssin ominaisuuksia...................
kaikille a R. 1 (R, +) on kommutatiivinen ryhmä, 2 a(b + c) = ab + ac ja (b + c)a = ba + ca kaikilla a, b, c R, ja
Renkaat Tarkastelemme seuraavaksi rakenteita, joissa on määritelty kaksi binääristä assosiatiivista laskutoimitusta, joista toinen on kommutatiivinen. Vaadimme muuten samat ominaisuudet kuin kokonaisluvuilta,
MS-C1340 Lineaarialgebra ja
MS-C1340 Lineaarialgebra ja differentiaaliyhtälöt Matriisinormi, häiriöalttius Riikka Kangaslampi Kevät 2017 Matematiikan ja systeemianalyysin laitos Aalto-yliopisto Matriisinormi Matriisinormi Matriiseille
Juuri 11 Tehtävien ratkaisut Kustannusosakeyhtiö Otava päivitetty
Kertaus K1. a) 72 = 2 36 = 2 2 18 = 2 2 2 9 = 2 2 2 3 3 = 2 3 3 2 252 = 2 126 = 2 2 63 = 2 2 3 21 = 2 2 3 3 7 = 2 2 3 2 7 syt(72, 252) = 2 2 3 2 = 36 b) 252 = 72 3 + 36 72 = 36 2 syt(72, 252) = 36 c) pym(72,
Nimittäin, koska s k x a r mod (p 1), saadaan Fermat n pienen lauseen avulla
6. Digitaalinen allekirjoitus Digitaalinen allekirjoitus palvelee samaa tarkoitusta kuin perinteinen käsin kirjotettu allekirjoitus, t.s. Liisa allekirjoittaessaan Pentille lähettämän viestin, hän antaa
2.2.1 Ratkaiseminen arvausta sovittamalla
2.2.1 Ratkaiseminen arvausta sovittamalla Esimerkki: lomitusjärjestäminen (edellä) Yleistys: Ratkaistava T (1) c T (n) g(t (1),..., T (n 1), n) missä g on n ensimmäisen parametrin suhteen kasvava. (Ratkaisu
Satunnaisalgoritmit. Topi Paavilainen. Laskennan teorian opintopiiri HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos
Satunnaisalgoritmit Topi Paavilainen Laskennan teorian opintopiiri HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos Helsinki, 23. helmikuuta 2014 1 Johdanto Satunnaisalgoritmit ovat algoritmeja, joiden
Algebra I Matematiikan ja tilastotieteen laitos Ratkaisuehdotuksia harjoituksiin 3 (9 sivua) OT
Algebra I Matematiikan ja tilastotieteen laitos Ratkaisuehdotuksia harjoituksiin 3 (9 sivua) 31.1.-4.2.2011 OT 1. Määritellään kokonaisluvuille laskutoimitus n m = n + m + 5. Osoita, että (Z, ) on ryhmä.
R 1 = Q 2 R 2 + R 3,. (2.1) R l 2 = Q l 1 R l 1 + R l,
2. Laajennettu Eukleideen algoritmi Määritelmä 2.1. Olkoot F kunta ja A, B, C, D F [x]. Sanotaan, että C jakaa A:n (tai C on A:n jakaja), jos on olemassa K F [x] siten, että A = K C; tällöin merkitään
811312A Tietorakenteet ja algoritmit, , Harjoitus 3, Ratkaisu
811312A Tietorakenteet ja algoritmit, 2018-2019, Harjoitus 3, Ratkaisu Harjoituksessa käsitellään algoritmien aikakompleksisuutta. Tehtävä 3.1 Kuvitteelliset algoritmit A ja B lajittelevat syötteenään
Matematiikan johdantokurssi, syksy 2016 Harjoitus 11, ratkaisuista
Matematiikan johdantokurssi, syksy 06 Harjoitus, ratkaisuista. Valitse seuraaville säännöille mahdollisimman laajat lähtöjoukot ja sopivat maalijoukot niin, että syntyy kahden muuttujan funktiot (ks. monisteen
ICS-C2000 Tietojenkäsittelyteoria Kevät 2016
ICS-C2000 Tietojenkäsittelyteoria Kevät 206 Kierros 0, 2. 24. maaliskuuta Huom! Perjantaina 25. maaliskuuta ei ole laskareita (pitkäperjantai), käykää vapaasti valitsemassanne ryhmässä aiemmin viikolla.
Esimerkkejä polynomisista ja ei-polynomisista ongelmista
Esimerkkejä polynomisista ja ei-polynomisista ongelmista Ennen yleisempiä teoriatarkasteluja katsotaan joitain tyypillisiä esimerkkejä ongelmista ja niiden vaativuudesta kaikki nämä ongelmat ratkeavia
Matematiikassa väitelauseet ovat usein muotoa: jos P on totta, niin Q on totta.
Väitelause Matematiikassa väitelauseet ovat usein muotoa: jos P on totta, niin Q on totta. Tässä P:tä kutsutaan oletukseksi ja Q:ta väitteeksi. Jos yllä oleva väitelause on totta, sanotaan, että P:stä
(d) 29 4 (mod 7) (e) ( ) 49 (mod 10) (f) (mod 9)
1. Pätevätkö seuraavat kongruenssiyhtälöt? (a) 40 13 (mod 9) (b) 211 12 (mod 2) (c) 126 46 (mod 3) Ratkaisu. (a) Kyllä, sillä 40 = 4 9+4 ja 13 = 9+4. (b) Ei, sillä 211 on pariton ja 12 parillinen. (c)
Todistusmenetelmiä Miksi pitää todistaa?
Todistusmenetelmiä Miksi pitää todistaa? LUKUTEORIA JA TO- DISTAMINEN, MAA11 Todistus on looginen päättelyketju, jossa oletuksista, määritelmistä, aksioomeista sekä aiemmin todistetuista tuloksista lähtien
Vektorien pistetulo on aina reaaliluku. Esimerkiksi vektorien v = (3, 2, 0) ja w = (1, 2, 3) pistetulo on
13 Pistetulo Avaruuksissa R 2 ja R 3 on totuttu puhumaan vektorien pituuksista ja vektoreiden välisistä kulmista. Kuten tavallista, näiden käsitteiden yleistäminen korkeampiulotteisiin avaruuksiin ei onnistu
Mitään muita operaatioita symbolille ei ole määritelty! < a kaikilla kokonaisluvuilla a, + a = kaikilla kokonaisluvuilla a.
Polynomit Tarkastelemme polynomirenkaiden teoriaa ja polynomiyhtälöiden ratkaisemista. Algebrassa on tapana pitää erillään polynomin ja polynomifunktion käsitteet. Polynomit Tarkastelemme polynomirenkaiden
Tietorakenteet, laskuharjoitus 2,
Tietorakenteet, laskuharjoitus, 6.-9.1 Muista TRAKLA-tehtävien deadline 31.1. 1. Tarkastellaan ensin tehtävää yleisellä tasolla. Jos funktion T vaativuusluokka on O(f), niin funktio T on muotoa T (n) =
1. Esitä rekursiivinen määritelmä lukujonolle
Matematiikan laitos Johdatus Diskrettiin Matematiikkaan Harjoitus 4 24.11.2011 Ratkaisuehdotuksia Aleksandr Pasharin 1. Esitä rekursiivinen määritelmä lukujonolle (a) f(n) = (2 0, 2 1, 2 2, 2 3, 2 4,...)
MITEN RATKAISEN POLYNOMIYHTÄLÖITÄ?
MITEN RATKAISEN POLYNOMIYHTÄLÖITÄ? Polynomiyhtälön ratkaiseminen Eri lajin yhtälöiden ratkaisutavat poikkeavat toisistaan. Siksi on tärkeää tunnistaa yhtälötyyppi. Polynomiyhtälö on yhtälö, joka voidaan
Johdatus matemaattiseen päättelyyn
Johdatus matemaattiseen päättelyyn Maarit Järvenpää Oulun yliopisto Matemaattisten tieteiden laitos Syyslukukausi 2015 1 Merkintöjä Luonnollisten lukujen joukko N on joukko N = {1, 2, 3,...} ja kokonaislukujen
Matematiikan tukikurssi
Matematiikan tukikurssi Kurssikerta 4 Jatkuvuus Jatkuvan funktion määritelmä Tarkastellaan funktiota f x) jossakin tietyssä pisteessä x 0. Tämä funktio on tässä pisteessä joko jatkuva tai epäjatkuva. Jatkuvuuden
Induktio, jonot ja summat
Induktio, jonot ja summat Matemaattinen induktio on erittäin hyödyllinen todistusmenetelmä, jota sovelletaan laajasti. Sitä verrataan usein dominoefektiin eli ketjureaktioon, jossa ensimmäisen dominopalikka
Analyysi III. Jari Taskinen. 28. syyskuuta Luku 1
Analyysi III Jari Taskinen 28. syyskuuta 2002 Luku Sisältö Sarjat 2. Lukujonoista........................... 2.2 Rekursiivisesti määritellyt lukujonot.............. 8.3 Sarja ja sen suppenminen....................
Salausmenetelmät. Veikko Keränen, Jouko Teeriaho (RAMK, 2006)
Salausmenetelmät Veikko Keränen, Jouko Teeriaho (RAMK, 2006) LUKUTEORIAA JA ALGORITMEJA 2. Eukleideen algoritmi à 2.1 Suurimman yhteisen tekijän tehokas laskutapa Tässä luvussa tarkastelemme annettujen
Testaa taitosi 1: Lauseen totuusarvo
Testaa taitosi 1: Lauseen totuusarvo 1. a) Laadi lauseen A (B A) totuustaulu. b) Millä lauseiden A ja B totuusarvoilla a-kohdan lause on tosi? c) Suomenna a-kohdan lause, kun lause A on olen vihainen ja
Ratkaisut Summa on nolla, sillä luvut muodostavat vastalukuparit: ( 10) + 10 = 0, ( 9) + 9 = 0,...
Ratkaisut 1 1. Summa on nolla, sillä luvut muodostavat vastalukuparit: ( 10) + 10 = 0, ( 9) + 9 = 0,.... Nolla, koska kerrotaan nollalla. 3. 16 15 50 = ( 8) 15 50 = (8 15) ( 50) = 1000 500 = 500 000. 4.
Diskreetin matematiikan perusteet Laskuharjoitus 1 / vko 8
Diskreetin matematiikan perusteet Laskuharjoitus 1 / vko 8 Tuntitehtävät 1-2 lasketaan alkuviikon harjoituksissa ja tuntitehtävät 5- loppuviikon harjoituksissa. Kotitehtävät 3-4 tarkastetaan loppuviikon
Numeeriset menetelmät
Numeeriset menetelmät Luento 2 To 8.9.2011 Timo Männikkö Numeeriset menetelmät Syksy 2011 Luento 2 To 8.9.2011 p. 1/33 p. 1/33 Lukujen tallennus Kiintoluvut (integer) tarkka esitys aritmeettiset operaatiot
