perjantai 24. huhtikuuta 2009

Vaihdanta.

Olen jo aikaisemmin kirjoitellut häviöttömästä pakkaamisesta. Tämä juttu ei tuo hirveästi uusia tietoja. Mutta ymmärtämistä se voi helpottaa; Tämä tarina on tavallaan analogian, vertauksen kautta tehty juttu, joka tekee siitä ymmärrettävän.

Ongelmana on sana "pakkaaminen". Se kun tuo mieleen suoraan pienentämisen. Mutta entä jos sana vaidetaankin muotoon "vaihtaminen"? No compression - Switch!

Häviöttömässä pakkaamisessahan on kyse vaihdannasta. Karkeasti sanoen luku vaihdetaan toiseen lukuun. Ennen tietokoneaikaa tätä olisi voinut olla vaikeaa selittää, mutta bittejähän tämäkin blogiviesti on. Numeroita. Periaatteessa sitä voisi kertoa vaikkapa tämän blogiartikkelin jollain toisella blogiartikkelilla ja saada vastauksen. Tosin mitään järkeähän tässä ei olisi, mutta voisi.

Pakkausalgoritmi vaihtaa numeroita keskenään ja purkaminen vaihtaa ne takaisin. Siinä on oltava muutamia ehtoja:
1: Kun pakataan, samaa lopputulosta ei tule kahdesta eri lähtökohdasta. Muuten tästä tulee häviöllinen pakkaus: Häviää tietoa juuri sen verran, että ei purkuvaiheessa tiedetä mikä näistä vaihtoehdoista on se alkuperäinen.
2: Jokainen syöte on voitava lähettää sen läpi. Tämä ei tarkoita että kaikkia olisi käsiteltävä: Esimerkiksi pakkausalgoritmi, jossa sotasuunnitelma vaihtuu "H" -kirjaimeksi ja takaisin, ja toisin päin, muuta ei käsitellä. Mutta se pakkaa sen yhden viestin. Muiden kohdalla B=B, C=C. Kaikki merkkijonot voidaan saada pakattua ja purettua, eli merkkijonona vaihdetaan siten että purkamisella saadaan takaisin juuri se, mitä ollaan ensin pakattu. Tämä on tärkeää. Ilman purkamismahdollisuutta ei oikeastaan ole järkevää puhua pakkaamisestakaan. Ilman yksiselitteisyyttä ei voida puhua häviöttömästä pakkaamisesta. (Ja muustahan en tässä höpise.)

Toisin sanoen pakatessa sanotaan että "vaihda tuo numero A tuohon numeroon B". Ongelmana on tietysti se, että jos pakkausalgoritmin on tuotettava kaikki, sen on tuotettava myös se numero B. Sitä ei voi merkitä itsellään, koska muutenhan purku ei osaisi erottaa olisiko se A vai B. Ja kun kaikkia on käsiteltävä, on oltava niin että B:kin saataisiin jotenkin pakattua.

Tässä käy niin, että lyhyempiin vaihtaminen ei onnistunut aina. Kolmella merkillä kun voidaan ilmoittaa monta enemmän kuin 2 merkillä. Tästä seuraa se, että on pakko joskus ottaa sellainen paikka, joka on pidempi kuin se joka vaihdetaan. Kaikkea ei voi pakata. Itse asiassa esimerkiksi jos pakkaus vaihtaa "päikseen" vaihtoehtoja, se että A vaihtuu lyhyemmäksi B:ksi tarkoittaa sitä että jos kyseessä on A:n pakkaus, se pienenee, mutta jos B:n pakkaaminen, se kasvaa A:ksi. Tällöin puolet kasvattavat ja puolet kutistavat. Samoin käy keskimäärin, vaikka ottaisimme A:n, jonka vaihtaisimme lyhyempään B:hen, jonka vaihtaisimme lyhyempään C:hen... kunnes vaihtaisimme Z:tan A:han. Tällöin juuri niin paljon kuin onnistumme tässä A...Y -ketjussa nappaamaan talteen, rymähtää niskaan aina Z:tan kohdalla. Ja kun Z on pakko ottaa huomioon, eikä sitä saa jättää pois, on selvää että näin tapahtuu usein.

Mutta tietysti pystytään parempaan kuin tuo karkea esitys. Pakkaamisesta saadaan pienellä tempulla paljon järkevämpää. Toki se ei muuta vääräksi mitään, mitä esitin.

Esimerkiksi nerokkaassa (ei ehkä kaikista nerokkaimmassa, mutta kuitenkin nerokkaassa) Huffmanin koodauksessa vaihdantaideaa on kehitetty aika pitkälle. Karkeasti sanoen se perustuu siihen, että se käy läpi tekstin. Jos siinä on joitain merkkejä paljon, se ottaa ne talteen "hyviksi vaihdettaviksi" ja antaa niille lyhyemmän symbolin, johon tämä toiste vaihdetaan. Eli kun analyysi aloitetaan, jokainen merkki ja yhdistelmä on samanarvoinen, mutta sen arvo muuttuu esiintymistiheyden mukana. Kaksi harvinaisinta yhdistetään puuksi ja yhdistetään kunnes näistä muodostetaan puu. Eli jos aineistossa on toistetta, tästä merkistä tulee "painava". Tässä sen polusta puuhun tulee lyhyt verrattuna muihin. tämä taas tarkoittaa sitä että sen bittiesityksestä tulee lyhyempi. Kun tieto tästä ympätään aineistoon, se pakkaa aineiston jos siinä on toistuvia jaksoja - eli jos sillä on vähän rakennetta. Tämä tarkoittaa tietysti sitä että harvinaisista sarjoista tulee "kevyitä" ja niiden bittiesitykset kasvavat. Mutta kun "kutistumisia" on enemmän kuin "levenemisiä", pakkaus onnistuu yleensä.

Tämä tarkoittaa sitä että pakkausalgoritmit harjoittavat eri tavalla fiksuja vaihtoja. On vain päätettävä mitkä ovat sellaisia joista me pidämme ja joista emme. Jos ne joita haluamme pakata, ovat rakenteeltaan tietynlaisia, voimme käyttää tätä hyväksemme. Ne muunlaiset tietysti kasvaisivat ikään kuin "kostoksi"; Joudumme antamaan niille isomman numeron, mutta käytännössä tämä ei haittaa koska niitä ei olla pakkaamassa.
Vaihtaminen on toisaalta hyvä, koska voin käyttää tätä aasinsilta -artikkelina, kun jossain vaiheessa kirjoittelen joitain asioita salaamisesta. Siinäkin on kyse vaihtamisesta. Merkki vaihdetaan toiseen. Siinä on hieman samantapaisia asioita.

3 kommenttia:

MrrKAT kirjoitti...

Turbo Pascal-kielessä oli paljon begin end for to repeat until sanoja. Ja tein ohjelman(oik. simulaation), joka korvaa niitä vähän käytetyillä ascii-koodeilla (>128..255 muistaakseni) ja sain nämä sain sitten pkzip/lzh:lla pakattua tiukemmaksi kuin nuo aikansa parhaat pakkaajat yksinään ikinä saivat. (Siis teoreettisesti simulaatiolla, ihan oikeasti en ikinä varsinaisesti tehnyt lopullista kätevää ohjelmalähdekoodin pakkausohjelmaa, tuo akateeminen lopputulos riitti mulle).

Tuomo "Squirrel" Hämäläinen kirjoitti...

Tuon pitäisi kyllä toimia, jopa melko hyvin - siis jos ohjelmalähdekoodin pakkaus on nimen omaan se "tarve missä".

Itsellä ei ole kuin epäonnistuneita kokeiluja pakkaamisesta. Kaikki jutut, mitä on itse keksinyt on paljastunut joko kliseisiksi virheiksi tai vaan virheiksi. Kantapään kautta sitten on oppinut, jos ei muuta, niin luottamaan ammattilaisiin. :) Ei kovin innovatiivista, mutta jotain konkreettista kuitenkin kertyy hihaan.

Se, mikä eniten ihmetyttää, on kuitenkin se, miten paljon musiikki ja puhe tiivistyy. Katsoo jotain MP3 -tiedostoa ja vertaa johonkin äänen suoraan bittiesitykseen. Puhe ja kieli ja musiikki on kuin valtava kasa toisteisuutta. Muuten ei pakkaamistaso selity.

Tietty, jos häviötä saa olla, niin laatu on kuitenkin niin hyvä, että lopputulos on sama. Että on turhaa roskaa, jonka voi leikata pois ilman että sitä lainkaan huomaa. Se on tosi epäintuitiivista. Luulisi että juuri puhe, ja se mitä ihminen tekee, olisi jotenkin erityisen fiksua, rakennerikasta, kompleksista. Mutta ei. Niin vaan on väärässä arkijärki.

MrrKAT kirjoitti...

Vokooderi(vocoder) keksittiin ennen WWII:ta ja päätarkoitus puheensalaus, mutta sillä voi pakata puhetta 1:26, jopa 2.4kbit/s:ään. (mun wav-mp3-muuntimessa alarajana on 8kbit/s).
Periaate on jotenkin että noukitaan puheen kantoaalto ja muu osa tutkitaan filtterikaistoilla ja lähetetään vain niiden verhokäyrä numeroina tms.

Nykyään päätarkoitus ollee generoida robottipuhe scifiin tai käyttää musatehosteena.

Klassinen musa on usein puristettavissa tiiviiksi mideiksi (netissä löytyy) eli about nuoteiksi. Esim. Bachin "Concerto for Two Harpsichords in C minor
BWV 1060 by Marcelo Copia M" vain 0.096Mt-tiedosto.*

Mutta öh..krhm.. syntikkakonemusa on kompleksisempaa. Tyypllisesti 3Mt-"nuotti"tiedostoja :)

*http://www.jsbach.net/midi/midi_concertos.html
(Sydäntäni lämmitti muuten hirmuisesti tuosta minulle vanhastaan tutusta Bach-sivusta tekemäni löytö: alalaidassa on mainos "Expelled Exposed" ..what Ben Stein isn't telling..)