Asymptoottinen suoritusaika

**Asymptoottinen suoritusaika** kuvaa algoritmin suoritusajan rajoja suhteessa algoritmin käsittelemän tietojoukon kokoon. Tietojoukon koon kasvaessa algoritmin suoritusaika lähestyy, mutta ei koskaan lähestymissuunnasta riippuen ylitä tai alita, asymptoottista rajaa. Ajan yksikkönä käytetään yhtä algoritmin suorittamaa askelta. Esimerkiksi hyvin sekoitettu korttipakka, jossa on N korttia voidaan järjestää arvojärjestykseen käymällä pakka läpi korkeintaan N kertaa ja jos havaitaan vierekkäiset kortit väärässä järjestyksessä, vaihdetaan näiden paikkaa (kuplalajittelu). Tällöin korttipakan järjestämisen asymptoottinen ylärajan sanotaan olevan *O(n<sup>2</sup>)*. Jos korttipakka on jo järjestyksessä, se havaitaan käymällä kaikki kortit läpi, mistä saadaan asymptoottiseksi alarajaksi *Θ*(n). 

Puhtaan matematiikan ja mekaanisen laskennan välillä on useita eroja, joista yksi on monien matematiikan funktioiden asymptoottinen luonne. Mikäli näitä funktioita pyritään ratkaisemaan alkeisoperaatioiden avulla, laskenta-aika venyy. Piin desimaalien laskenta on tästä yksi esimerkki. Käytännössä usein riittää kuvata yhtälö yksinkertaisemmassa muodossa, koska käsiteltävien desimaalien määrä monissa järjestelmissä (esimerkiksi talous-) on rajoitettu. Alla on matemaattinen kuvaus riittävällä tarkkuudella ratkeavasta funktiosta.

Aikavaatimuksen (kompleksisuus) lisäksi algoritmilla voi olla tilavaatimus eli paljonko resursseja (muistia) suoritus voi käyttää. Lisäksi suorituksen kustannus on laskenut sekä muistilatenssin suhteellinen vaikutus suoritusaikaan on kasvanut. Välimuistihutien vaikutus on nykyään merkittävä tekijä algoritmien suunnittelussa.

## Taustaa
J. Hartmanis ja R. E. Stearns julkaisivat vuonna 1965 artikkelin *On The Computational Complexity of Algorithms*, jossa laskennallista (komputaatio) kompleksisuutta verrattiin miten nopeasti kuvitteellinen Turingin kone pystyy käsittelemään käskynauhaa. Abstraktia mallia käytettiin, koska kaikki digitaaliset tietokoneet ovat ideaalisessa muodossa Turingin koneen kaltaisia.

## Merkintätavat
Funktioiden kasvunopeudesta käytetään useita eri merkintätapoja. Tässä niistä yleisimmät, eli
* Bachmann–Landau -notaatio tai *iso-O -notaatio* – aidosti ylhäältä rajoitettu.
* Theta-notaatio tai *iso theta* (*Θ*) – aidosti alhaalta ja ylhäältä rajoitettu.
* Iso-omega -notaatio (*Ω*)

Lisäksi vielä vähemmän käytetty merkintätapa:
* *ω*-notaatio – aidosti  alhaalta rajoitettu, joka tarkoittaa lyhyesti **Suoritukseen kuluu vähintään näin monta alkeisoperaatiota, mutta se voi kuluttaa enemmänkin**

## Iso-O -notaatio

Yleisesti *iso-O -notaationa* tunnettu merkintätapa on tunnettu myös Bachmann–Landau -notaationa.
Myös termiä *Ordo-notaatio* käytetään.

Matemaattinen merkitys:
: *Ο*(g(n)) = {f(n) | 0 ≤ f(n) ≤ c2g(n) kaikilla n ≥ n0}
..missä c2 on jokin positiivinen reaaliluku ja n0 on jokin luonnollinen luku.

Merkitään, että f(n) = *Ο*(g(n)).

Ordo-merkintä kuvastaa pahinta mahdollista tapausta. Se rajoittaa ylhäältä päin aidosti algoritmin suoritusaikaa. Esimerkiksi pikalajittelu toimii nopeimmin jos alkiot ovat syötteessä mahdollisimman sekaisin. Lisäyslajittelu toimii nopeimmin jos alkiot ovat jo järjestyksessä, ja hitaimmin jos käänteisessä järjestyksessä. Ordo-notaatiolla jätetään syötteen aiheuttama suoritusajan vaihtelu huomiotta, ja keskitytään vain pahimpaan mahdolliseen tapaukseen, jolloin lajittelu kestää eniten aikaa.

Ordo-notaatiolla siis ilmoitetaan:
:**Suoritukseen kuluu maksimissaan näin monta alkeisoperaatiota syötteestä riippumatta, mutta se voi valmistua vähemmälläkin**

## Theta-notaatio

Matemaattinen merkitys:
: *Θ*(g(n)) = {f(n) | 0 ≤ c1*g(n) ≤ f(n) ≤ c2g(n) kaikilla n ≥ n0}
.. missä c1,c2 on jokin positiivinen reaaliluku ja n0 on jokin luonnollinen luku.

f(n) on jokin *Θ*(g(n)):ään sisältyvä funktio, toisin sanoen: on olemassa sellaiset vakiot c1,c2 että f(n) on jossain välillä c1*g(n)..c2*g(n), silloin kun n kasvaa riittävän suureksi. 

Θ(g(n)) on siis itse asiassa funktioiden joukko. 

Theta-merkintä kertoo sekä hitaimman että nopeimman suoritusajan. Toisin sanoen, algoritmin toimiessa *Θ*(n2) -ajassa, se Ordo-notaation perusteellakin toimii *Ο*(n2) -ajassa. Mutta, jos algoritmi toimii *Ο*(n2) ajassa, siitä ei välittömästi seuraa, että algoritmi toimisi *Θ*(n2) -ajassa, sillä *Θ*(f(n)) sisältää *Ο*(f(n)):n mutta *Ο*(f(n)) ei sisällä *Θ*(f(n)):aa.

Theta-notaatiolla siis ilmoitetaan:
: **Tarvittavien alkeisoperaatioiden määrä on aina tällä välillä syötteestä riippumatta**

## Esimerkki

Osoitetaan, että 12n8 ≠ *Ο*(n7).

Väite: 
: 12n8 ≠ *Ο*(n7) 
Tehdään vastaoletus:
: 12n8 = *Ο*(n7)
Tällöin on löydyttävä sellaiset c2 ja n0 että:
: 12n8 ≤ c2n7 kaikilla n ≥ n0
Mutta tällöinhän:
: 12n ≤ c2 kaikilla n ≥ n0
Josta seuraa ristiriita.

Vastaoletuksesta seuraa ristiriita, joten alkuperäinen väite on tosi, eli 12n8 ≠ *Ο*(n7).

Samalla periaatteella voidaan todistaa, että 12n7 = *Ο*(n8) on tosi.

## Lähteet

## Kirjallisuutta
* Sanjeev Arora & Boaz Barak: *Computational Complexity: A Modern Approach*, Draft (PDF)