2 Sanoja järjestävän funktion ohjelmoiminen

Samankaltaiset tiedostot
Vaihtoehtoinen tapa määritellä funktioita f : N R on

Rekursio. Funktio f : N R määritellään yleensä antamalla lauseke funktion arvolle f (n). Vaihtoehtoinen tapa määritellä funktioita f : N R on

Rekursiolause. Laskennan teorian opintopiiri. Sebastian Björkqvist. 23. helmikuuta Tiivistelmä

Rekursiiviset palautukset [HMU 9.3.1]

Tietojenkäsittelyteorian alkeet, osa 2

Vasen johto S AB ab ab esittää jäsennyspuun kasvattamista vasemmalta alkaen:

Todistus: Aiemmin esitetyn mukaan jos A ja A ovat rekursiivisesti lueteltavia, niin A on rekursiivinen.

Säännölliset kielet. Sisällys. Säännölliset kielet. Säännölliset operaattorit. Säännölliset kielet

DFA:n käyttäytyminen ja säännölliset kielet

Äärellisten automaattien ja säännöllisten kielten ekvivalenssi

Esitetään tehtävälle kaksi hieman erilaista ratkaisua. Ratkaisutapa 1. Lähdetään sieventämään epäyhtälön vasenta puolta:

on rekursiivisesti numeroituva, mutta ei rekursiivinen.

Johdatus lukuteoriaan Harjoitus 2 syksy 2008 Eemeli Blåsten. Ratkaisuehdotelma

Todistusmenetelmiä Miksi pitää todistaa?

Pysähtymisongelman ratkeavuus [Sipser luku 4.2]

f(n) = Ω(g(n)) jos ja vain jos g(n) = O(f(n))

Diskreetin Matematiikan Paja Ratkaisuhahmotelmia viikko 1. ( ) Jeremias Berg

Matematiikan tukikurssi, kurssikerta 2

4 Matemaattinen induktio

Jos sekaannuksen vaaraa ei ole, samastamme säännöllisen lausekkeen ja sen esittämän kielen (eli kirjoitamme R vaikka tarkoitammekin L(R)).

Ensimmäinen induktioperiaate

Ensimmäinen induktioperiaate

Ratkeavuus ja efektiivinen numeroituvuus

Johdatus diskreettiin matematiikkaan Harjoitus 5, Ratkaise rekursioyhtälö

Lukion matematiikkakilpailun alkukilpailu 2015

Luonnollisten lukujen ja kokonaislukujen määritteleminen

Johdatus lukuteoriaan Harjoitus 11 syksy 2008 Eemeli Blåsten. Ratkaisuehdotelma

isomeerejä yhteensä yhdeksän kappaletta.

Matematiikan mestariluokka, syksy

Johdatus diskreettiin matematiikkaan (syksy 2009) Harjoitus 3, ratkaisuja Janne Korhonen

A ja B pelaavat sarjan pelejä. Sarjan voittaja on se, joka ensin voittaa n peliä.

Yhtälönratkaisusta. Johanna Rämö, Helsingin yliopisto. 22. syyskuuta 2014

Johdatus matematiikkaan

ICS-C2000 Tietojenkäsittelyteoria Kevät 2016

Matemaattisen analyysin tukikurssi

TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 8. syyskuuta 2016

Matematiikan johdantokurssi, syksy 2016 Harjoitus 11, ratkaisuista

811120P Diskreetit rakenteet

Kaikki kurssin laskuharjoitukset pidetään Exactumin salissa C123. Malliratkaisut tulevat nettiin kurssisivulle.

Johdatus matematiikkaan

1. Osoita, että joukon X osajoukoille A ja B on voimassa toinen ns. de Morganin laki (A B) = A B.

Matemaattisten työvälineiden täydentäviä muistiinpanoja

Lisää pysähtymisaiheisia ongelmia

Algoritmit 2. Demot Timo Männikkö

Vastaus 1. Lasketaan joukkojen alkiot, ja todetaan, että niitä on 3 molemmissa.

10 Matriisit ja yhtälöryhmät

Miten perustella, että joukossa A = {a, b, c} on yhtä monta alkiota kuin joukossa B = {d, e, f }?

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Matematiikan tukikurssi

1 Kertaus. Lineaarinen optimointitehtävä on muotoa:

1 Lukujen jaollisuudesta

Ohjelmoinnin perusteet Y Python

Hakupuut. tässä luvussa tarkastelemme puita tiedon tallennusrakenteina

Diskreetin matematiikan perusteet Laskuharjoitus 2 / vko 9

MS-C1340 Lineaarialgebra ja

Säännöllisten kielten sulkeumaominaisuudet

Derivaattaluvut ja Dini derivaatat

Diskreetin matematiikan perusteet Laskuharjoitus 1 / vko 8

Johdatus matemaattiseen päättelyyn

Liite 1. Laajennettu Eukleideen algoritmi suoraviivainen tapa

Säännöllisen kielen tunnistavat Turingin koneet

Tehtävä 1. Päättele resoluutiolla seuraavista klausuulijoukoista. a. 1 {p 3 } oletus. 4 {p 1, p 2, p 3 } oletus. 5 { p 1 } (1, 2) 7 (4, 6)

Sisältö. Sarjat 10. syyskuuta 2005 sivu 1 / 17

Joukot. Georg Cantor ( )

1. Esitä rekursiivinen määritelmä lukujonolle

Luonnollisten lukujen induktio-ominaisuudesta

58131 Tietorakenteet ja algoritmit (syksy 2015)

b) Määritä myös seuraavat joukot ja anna kussakin tapauksessa lyhyt sanallinen perustelu.

Predikaattilogiikan malli-teoreettinen semantiikka

TIEA241 Automaatit ja kieliopit, kevät 2011 (IV) Antti-Juhani Kaijanaho. 31. maaliskuuta 2011

Määritelmä, alkuluku/yhdistetty luku: Esimerkki . c) Huomautus Määritelmä, alkutekijä: Esimerkki

Testaa: Vertaa pinon merkkijono syötteeseen merkki kerrallaan. Jos löytyy ero, hylkää. Jos pino tyhjenee samaan aikaan, kun syöte loppuu, niin

Chomskyn hierarkia ja yhteysherkät kieliopit

Automaatit. Muodolliset kielet

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

Positiivitermisten sarjojen suppeneminen

missä on myös käytetty monisteen kaavaa 12. Pistä perustelut kohdilleen!

2.1. Tehtävänä on osoittaa induktiolla, että kaikille n N pätee n = 1 n(n + 1). (1)

Johdatus diskreettiin matematiikkaan Harjoitus 2, Osoita että A on hyvin määritelty. Tee tämä osoittamalla

8. Kieliopit ja kielet

Nopea kertolasku, Karatsuban algoritmi

Lukujonon raja-arvo 1/7 Sisältö ESITIEDOT: lukujonot

Karteesinen tulo. Olkoot A = {1, 2, 3, 5} ja B = {a, b, c}. Näiden karteesista tuloa A B voidaan havainnollistaa kuvalla 1 / 21

Relaation ominaisuuksia. Ominaisuuksia koskevia lauseita Sulkeumat. Joukossa X määritelty relaatio R on. (ir) irrefleksiivinen, jos x Rx kaikilla x X,

Konnektiivit. On myös huomattava, että vain joillakin luonnollisen kielen konnektiiveilla on vastineensa lauselogiikassa.

Esimerkkejä polynomisista ja ei-polynomisista ongelmista

T Syksy 2004 Logiikka tietotekniikassa: perusteet Laskuharjoitus 7 (opetusmoniste, kappaleet )

Joukossa X määritelty relaatio R on. (ir) irrefleksiivinen, jos x Rx kaikilla x X,

Tenttiin valmentavia harjoituksia

LUKUTEORIA johdantoa

= 5! 2 2!3! = = 10. Edelleen tästä joukosta voidaan valita kolme särmää yhteensä = 10! 3 3!7! = = 120

ja λ 2 = 2x 1r 0 x 2 + 2x 1r 0 x 2

Ohjelmoinnin perusteet Y Python

Injektio (1/3) Funktio f on injektio, joss. f (x 1 ) = f (x 2 ) x 1 = x 2 x 1, x 2 D(f )

Laskennan rajoja. TIEA241 Automaatit ja kieliopit, syksy Antti-Juhani Kaijanaho. 10. joulukuuta 2015 TIETOTEKNIIKAN LAITOS.

TIEA241 Automaatit ja kieliopit, kevät 2011 (IV) Antti-Juhani Kaijanaho. 16. maaliskuuta 2011

Matematiikan ohjelmointi. Joakim von Wright

Epäyhtälöt ovat yksi matemaatikon voimakkaimmista

Satunnaisalgoritmit. Topi Paavilainen. Laskennan teorian opintopiiri HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos

Ohjelmoinnin peruskurssien laaja oppimäärä

Transkriptio:

1 Tämän dokumentin tarkoitus Tämä dokumentti ei kuulu millään tavoin tenttialueeseen, enkä ota vastuuta sen lukemisen aiheuttamista vahingoista. Tässä dokumentissa esitetään esimerkin kautta, miten matematiikan kielessä voi harrastaa ns. funktionaalista ohjelmointia. Tarkemmin, esitetään eräs versio ns. lisäyslajittelu-algoritmista matematiikan kielellä, määrittelemällä se funktiona sanoista sanoihin rakentellisella induktiolla. Lisäksi todistetaan, että algoritmi toimii. Monisteen Luvussa 1.6 tehdään samaa asiaa hieman eri kielellä ja eri esimerkkiongelmille. Lauseen 1 todistus on kirjoitettu Proof-of-concept -mielessä, koska luennoitsija itse halusi nähdä onnistuuko induktiotodistus tässä esimerkissä suoraviivaisesti (näyttäisi onnistuvan). Todistuksen yksityiskohtainen lukeminen ei välttämättä ole pedagogisesti hyödyllistä. 2 Sanoja järjestävän funktion ohjelmoiminen Olkoon Σ äärellinen 1 aakkosto, jossa on määritelty jokin täysi järjestys, eli kun a, b Σ, niin tasan yksi kolmesta relaatiosta a < b, a = b, a > b pätee. Esimerkiksi voi olla Σ N. Esimerkeissä aakkosto on Σ = {0, 1, 2} (eli aakkoston Σ kirjaimet ovat 0, 1, 2), ja valitaan järjestykseksi 0 < 1 < 2. Nyt määritellään induktiivisesti kaksi funktiota, s : Σ Σ on sanan järjestävä funktio, eli esim. halutaan s(010) = 001. Tämä funktio määritellään seuraavasti käyttäen apuna funktiota i: s(ɛ) = ɛ, s(a u) = i(a, s(u)). Funktio i : Σ Σ Σ on apufunktio, jonka idea on, että jos u on jo järjestyksessä ja a Σ, niin i(a, u) = v, missä v on muuten sama kuin u, mutta siihen on sijoitettu a oikeaan paikkaan Esimerkiksi i(1, 00112) = 001112. Määritellään i induktiivisesti: { abv jos b a i(a, ɛ) = a, i(a, b v) = b i(a, v) jos b < a Pythonilla sama näyttäisi tältä: # järjestysfunktio, jossa sama rekursio kuin kaavoissamme def s(w): if len(w) == 0: # tyhjä sana vastaa 0-pituista sanaa, sille ei tarvitse tehdä mitään return w else: # yleisessä tapauksessa w = a. u leikataan ulos a ja u a = w[0] u = w[1:] # s(w) = s(a.u) = i(a, s(u)) kuten kaavassa return i(a, s(u)) 1 Homma toimisi äärettömälle samoin ohjelmoinnissa tyypillisesti Σ olisi mielivaltainen tyyppi jossa on määritelty järjestysrelaatio, ja samoin voi tehdä matematiikassa. 1

# "insert"-funktio, taas samoilla kaavoilla määritelty def i(a, u): if len(u) == 0: # i(a, epsilon) = a return a else: b = u[0] v = u[1:] if b >= a: # Pythonissa sanoja pistetään yhteen +-merkillä eikä kertomerkillä. return a + b + v else: # i(a, b.u) = b. i(a, u) jos b < a return b + i(a, v) print (s("abbabaa")) # tämä printtaa aaaabbb kun ohjelma ajetaan Matemaattiset määritelmät voi tässä nähdä kyseisen Python-koodin käännöksenä matematiikan kielelle, jotta sen ominaisuuksia voi todistaa. (Tosin tein itse asian toisinpäin eli käänsin matemaattisen määritelmän Pythoniksi.) 3 Testi Lasketaan s(20110), jossa pitäisi siis olla 2, 0, 1, 1, 0 kasvavassa järjestyksessä. Näin todella käy: s(20110) = i(2, s(0110)) = i(2, i(0, s(110))) = i(2, i(0, i(1, s(10)))) = i(2, i(0, i(1, i(1, s(0))))) = i(2, i(0, i(1, i(1, i(0, ɛ))))) = i(2, i(0, i(1, i(1, 0)))) = i(2, i(0, i(1, 0 i(1, ɛ)))) = i(2, i(0, i(1, 0 1))) = i(2, i(0, 0 i(1, 1))) = i(2, i(0, 0 11)) = i(2, 0 011)) = 0 i(2, 0 11)) = 00 i(2, 1 1)) = 001 i(2, 1)) = 0011 i(2, ɛ)) = 00112 Tässä on aina laskettu sisin termi auki määritelmää käyttäen, ja ylimääräiset kertomerkit on pudoteltu pois välivaiheissa. Välivaiheita tuli tässä 15 kpl, ja 2

niiden määrää voisi vähän pudottaa todistamalla sopivia aputuloksia, tai tekemällä useampi sievennys kerralla. Joka tapauksessa tällä algoritmilla välivaiheita tulee monta, nimittäin pahimmillaan Ω(n 2 ) kappaletta, eli enemmän kuin Cn 2 jollekin vakiolle C, missä n on sanan pituus. Parempien algoritmien keksiminen ei kuitenkaan ole tämän kurssin asiaa. 4 Määritelmiä: Mitä tarkoittaa järjestää? Ennen kuin voidaan todistaa, että funktiomme todella järjestää sanan, täytyy määritellä, mitä tarkoittaa järjestää. Määrittelemme tämänkin induktiolla. Intuitiivisesti funktio s : Σ Σ on sanan järjestävä funktio, jos kaikille sanoille u, s(u) sisältää samat kirjaimet kuin u, ja s(u):ssa kirjaimet ovat järjestyksessä. Kirjaimet ovat järjestyksessä, jos peräkkäiset kirjaimet ovat aina kasvavassa järjestyksessä, eli u Σ on järjestyksessä jos kaikille i, u i u i+1, missä u i tarkoittaa u:n i:nnettä kirjainta. Voimme kirjoittaa tämän induktiolla: Määritellään järjestyksessä olevien sanojen joukko S Σ induktiivisesti: ɛ S, a S kaikille a Σ, ja jos b u S ja a b, a Σ, niin abu S. Nyt sana u on järjestyksessä jos u S, merkitään tätä ominaisuutta P (u). Todistetaan melko triviaali apulause. Lemma 1. Jos a, b Σ ja a b, niin ab S. Todistus. Suoraan määritelmästä b S eli b ɛ S, ja tällöin S:n määritelmän induktioaskeleesta saadaan a (b ɛ) = ab S. Määritellään sitten mitä tarkoittaa, että v:ssä ja u:ssa on samat kirjaimet. Yksi tapa määritellä tämä on, että kaikille kirjaimille a Σ, kirjainten a lukumäärä u:ssa ja v:ssä on sama. Merkitään tätä määrää u a ja määritellään se induktiivisesti: { 1 + u a jos b = a ɛ a = 0, b u a = u a muuten. Nyt sanotaan, että u:ssa ja v:ssä on samat kirjaimet, jos kaikille a Σ, u a = v a. Merkitään tätä ominaisuutta Q(u, v). Nyt halutaan, että funktiolla s : Σ Σ, joka määriteltiin Luvussa 2, on seuraava ominaisuus: u Σ : P (s(u)) Q(u, s(u)) eli s järjestää syötteeksi saamansa sanan u. Todistamme tämän seuraavassa luvussa. 5 Funktio s on todella järjestysfunktio Olemme määritelleet induktiivisesti funktion s ja määritelleet mitä tarkoittaa olla järjestyksessä ja sisältää samat kirjaimet. Nyt voimme todistaa induktiolla, että s on järjestysfunktio. Theorem 1. Olkoon u Σ mielivaltainen sana. Tällöin P (s(u)) ja Q(u, s(u)), eli s(u) on järjestyksessä ja sisältää samat kirjaimet kuin u. 3

Todistus. Todistetaan ensin ominaisuus P (s(u)), eli että s:n arvo s(u) on järjestyksessä jokaisella syötteellä. Pitää siis todistaa, että s(u) kuuluu joukkoon S, joka määriteltiin edellisessä luvussa. Todistetaan tämä rakenteellisella induktiolla: Lähtökohta on s(ɛ) = ɛ S. Induktioaskel on s(a u) = i(a, s(u)), missä induktio-oletuksesta seuraa, että s(u) S (koska u on yksinkertaisempi sana kuin a u). Riittää siis todistaa, että funktiolla i on ominaisuus, että jos v S ja a Σ, niin i(a, v) S. Todistetaan tämä rakenteellisella induktiolla v:n suhteen (mikä onnistuu, koska S määriteltiin induktiolla): Lähtökohdat ovat i(a, ɛ) ja i(a, b) kun a, b Σ. Tapaus i(a, ɛ) = a S on selvä. Tapauksessa i(a, b) joko a b tai b < a. Jos a b, niin i(a, b) = ab suoralla laskulla (eli suoraan määritelmästä), ja tällöin ab S Lemman 1 nojalla. Jos b < a, niin suoralla laskulla taas i(a, b) = ba ja taas ba S Lemman 1 nojalla. Joukon S määritelmässä askel on (kun nimetään vähän uudelleen kirjaimia), että jos c u S ja b c, b Σ, niin bcu S. Eli todistettaessa i:lle induktioaskelta tarvitsee käsitellä vain tapaus i(a, b (c u)) S missä c u S ja b c. Jos a b, niin suoralla laskulla (eli suoraan määritelmästä) i(a, b (c u))) = abcu, ja abcu S taas kerran suoraan S:n määritelmästä (bcu S ja a b joten tämä on vain S:n määritelmän induktioaskel). Muuten a > b jolloin i(a, b (c u)) = b i(a, c u) missä induktio-oletuksesta seuraa i(a, c u) S koska c u S on yksinkertaisempi kuin b (c u), ja koska b < a, erityisesti b a, joten S:n induktiivisesta määritelmästä seuraa i(a, b (c u)) = b i(a, c u) S. Olemme todistaneet, että todella P (s(u)) kaikille sanoille u. Todistetaan vielä Q(u, s(u)) kaikille sanoille u Σ. Tämä tehdään yllättäen rakenteellisella induktiolla u:n suhteen. Lähtötapaus Q(ɛ, s(ɛ)) on triviaali, koska s(ɛ) = ɛ ja selvästi ɛ a = ɛ a kaikille a Σ. Sitten induktioaskel: Olkoon a Σ, ja b u Σ. Nyt s(b u) = i(b, s(u)), ja induktio-oletuksesta seuraa u a = s(u) a kaikille a. Koska b u a = u a + 1 jos a = b ja b u a = u a jos a b, riittää todistaa, että i:llä on se ominaisuus, että jos a b niin i(b, v) a = v a ja jos a = b niin i(b, v) a = v a + 1 (eli toisin sanoen, i(b, v):ssa on v:n kirjaimet sekä yksi ylimääräinen b). Tämä todistetaan yllättäen rakenteellisella induktiolla v:n suhteen. Käsitellään tässä vain tapaukset b = a, tapaukset a b menevät aina samaan tyyliin: Lähtökohdat i(b, ɛ) a = b a = 1 = ɛ a + 1 kun b = a ja i(b, c) {bc, cb} 4

joten i(b, c) a = c a + 1 suoralla laskulla kun b = a (ja tosiaan tapaukset b a samaan malliin). Sitten induktioaskel S:n induktiivista määritelmää pitkin: Olkoon v = c (d v ) S, c d, c, d Σ. Jos b c niin i:n määritelmästä laskemalla saadaan Jos taas b > c niin i(b, c (d v ) a = bcdv a = 1 + cdv a = v a + 1 i(b, c (d v ) a = c i(b, d v ) a. Tässä i(b, d v ) a = d v + 1. Jos nyt c = a, niin v a = d v + 1 jolloin i(b, c (d v ) a = c i(b, d v ) a = 1 + i(b, d v ) a = d v + 2 = v a + 1 ja jos c a, niin lasku menee samaan tyyliin. 6 Lyhyesti formaalisista metodeista Formaalit metodit ovat tietojenkäsittelytieteen haara, jossa tutkitaan erityisesti ohjelmien toimivuuden aukotonta todistamista. Tämä pohjautuu siihen, että matematiikan kielellä voi ohjelmoida kaiken, minkä voi ylipäätään ohjelmoida, mutta matematiikassa voi mennä ohjelmointia pidemmälle, ja todistaa, että ohjelma toimii. Tässä on kaksi vaihetta: 1. Formalisoidaan ominaisuus, joka halutaan todistaa (esimerkissämme tämä ominaisuus on, että s järjestää sanan kirjaimet kasvavaan järjestykseen, eli Luvun 4 ominaisuudet P ja Q). 2. Todistetaan (esim. induktiolla) että algoritmilla on todella tämä formalisoitu ominaisuus. (Lause 1.) Ensimmäinen vaihe näistä on myös ohjelmointia, koska meidän on matematiikan kielellä ohjelmoitava, mitä tarkoittaa olla järjestyksessä. Tässä vaiheessa voi myös sattua virheitä! Onko hommassa siis mitään järkeä, jos virhe voi yhtä hyvin sattua siinä vaiheessa kun päätämme mitä haluamme todistaa? On! Jos myöhemmin vaihdamme algoritmia, jolla järjestämme sanan, esimerkiksi nopeampaan QuickSort- tai MergeSort-algoritmiin, 2 jotka myös on helppo ohjelmoida matematiikan kielellä, niin meidän ei tarvitse uudestaan määritellä mitä tarkoittaa olla järjetyksessä, vaan voimme suoraan lähteä todistamaan näiden algoritmien oikeellisuutta samalla määritelmällä. Eli siinä, missä algoritmi voi muuttua (koska sitä pitää esim. nopeuttaa, tai muuten tehostaa), määritelmät kuten olla järjestyksessä eivät yleensä muutu (koska ne ovat vain määritelmiä, eikä niiden tarvitse olla tehokkaita ). Eli Lukua 4 ei tarvitsisi muuttaa lainkaan, vaikka funktion s induktiivinen/rekursiivinen määritelmä vaihdettaisiin tehokkaampaan! 2 Näistä löytyy esim. Wikipediasta selkeät esitykset. 5

Toinen vaihe, jossa ominaisuus todistetaan, voi myös teoriassa mennä vikaan, jos sen tekee käsin: Joskus todistus on vaikeampi ymmärtää, kuin intuitiivinen selitys, eikä sitä hullukaan jaksa lukea. Esimerkiksi yllä oleva todistus, että järjestysfunktio s todella järjestää syötteensä, on suoraan sanottuna aika hirvittävä (eikä edes käsittele kaikkia tapauksia). Oikeassa elämässä algoritmit ovat kuitenkin paljon monimutkaisempia, ja algoritmista ei välttämättä oikeasti tiedä toimiiko se, ennen kuin todistaa asian. Tällöin todistuksessa hypätään tylsät osat yli, ja selitetään vain olennainen (mutta tällä tarkkuudella tehtynä Lauseessa 1 ei olisi mitään todistamista). Kuitenkin jo QuickSortin tapauksessa helpoin tapa selittää toimivuus, on selittää miksi funktion rekursiivinen kutsu tuottaa validin induktioaskeleen. Jos taas ollaan kiinnostuttu yksinkertaisista algoritmeista kuten s:lle annettu kaava, ja halutaan olla todella varmoja, että ohjelma todella toimii oikein (kaikissa tilanteissa), voi todistuksen voi kirjoittaa jossain todistustyökalussa (esim. Isabelle, Coq, HOL, Mizar...) ja käskeä tietokoneen tarkistamaan sen. Tämä vaatii toistaiseksi enemmän työtä, kuin todistuksen selittäminen ihmiselle, mutta todistustyökalut muuttuvat kaiken aikaa helppokäyttöisemmiksi, ja osaavat jo nyt usein automatisoida monia ilmeisiä askelia todistuksessa. Yllä annetun kaltainen induktiotodistus sopii periaatteessa melko suoraan tällaiseen työkaluun, joskin vaatii työkalun hyvää teknistä hallintaa. 6