1 while `m != 0` do
2 `k` := `n mod m`
3 `n` := `m`
4 `m` := `k`
Koska `0 = 7*0` ja `0 = 123*0`, ovat sekä 7 että 123 nollan tekijöitä.
Itse asiassa jokainen luonnollinen luku on nollan tekijä, sillä `0 = h*0`
pätee jokaisella `h`.
Siksi, jos alussa `n=m=0`, niin suurinta yhteistä tekijää ei ole olemassa.
Aputuloksia
Tekijän määritelmä on seuraava.
Kokonaisluku `h` on `I`:n tekijä jos ja vain jos on olemassa kokonaisluku `i`
siten, että `I = hi`.
Tulemme tarvitsemaan viisi aputulosta.
Todistamme ne tässä.
Jos `h` on `I`:n tekijä ja `J`:n tekijä, niin `h` on myös luvun `I+J`
tekijä.
Jos `h` on `I`:n tekijä ja `J`:n tekijä, niin `h` on myös luvun `I-J`
tekijä.
Jos `h` on `I`:n tekijä, niin `h` on myös luvun `IJ` tekijä.
Jos `J != 0` ja `h` on `I`:n ja `J`:n tekijä, niin `h` on myös luvun `I
mod J` tekijä.
MathCheck ei tunne symboleita `text(div)` ja `text(mod)`, mutta `n
\ text(div) \ m` saadaan kirjoittamalla |_n/m_|.
Jos `J != 0` ja `h` on lukujen `J` ja `I mod J` tekijä, niin `h` on myös
`I`:n tekijä.
SYT-algoritmin oikeellisuus
Tässä osassa osoitamme, että jos alussa `n != 0` tai `m != 0` niin
SYT-algoritmin vastaus on oikea.
Tärkeintä ei ole lopputulos vaan päättelyn harjoitteleminen, tai ainakin
päättelyn ymmärtämisen harjoitteleminen.
Tapauksessa `n=m=0` suurinta yhteistä tekijää ei ole olemassa, joten jätämme
sen tutkimatta.
Jotta alkuperäisten `n`:n ja `m`:n suurimmasta yhteisestä tekijästä olisi
helpompi puhua, annamme sille nimeksi `s`.
Tavoitteemme on osoittaa, että `n`:n lopullinen arvo on `s`.
Osoitetaan, että invariantti pätee silmukan alussa.
Tämä on yleensä helppoa.
Osoitetaan, että silmukan vartalon suoritus ei voi saada invarianttia pois
voimasta paitsi korkeintaan tilapäisesti.
Täsmällisemmin sanottuna: osoitetaan, että jos invariantti pätee silmukan
vartalon alussa, niin se pätee myös vartalon lopussa (mutta saa olla pois
voimasta keskellä vartaloa).
Koska silmukan vartalo voi olla iso, tämä on usein työlästä, mutta tällä
kertaa ei ole.
Tässä todistuksessa saa käyttää silmukan ehtoa.
Osoitetaan, että silmukan suoritus loppuu joskus.
Tämä on usein hyvin helppoa, mutta joskus erittäin vaikeaa.
Osoitetaan, että jos invariantti pätee ja silmukan ehto ei päde, niin
silmukan lopputulokselta haluttu asia pätee.
Tämäkin on yleensä helppoa.
Tämä menettely on pätevä seuraavasta syystä.
Käytämme SYT-algoritmin rivejä esimerkkinä.
Kohta 2 kertoo, että kun rivin 1 alussa ollaan ensimmäisen kerran
eli silmukkaa on kierretty nolla kierrosta, niin invariantti pätee.
Jos tällöin `m=0` niin SYT-algoritmi lopettaa.
Muussa tapauksessa suoritetaan silmukan vartalo siten, että invariantti päti
kun vartalon suoritus alkoi.
Kohta 3 kertoo, että invariantti pätee myös rivin 4 lopussa.
Rivin 4 lopusta joudutaan uudelleen rivin 1 alkuun, joten kun rivin 1 alussa
ollaan toisen kerran, niin invariantti pätee.
Jos tällöin `m=0` niin SYT-algoritmi lopettaa.
Muussa tapauksessa suoritetaan silmukan vartalo siten, että invariantti päti
kun vartalon suoritus alkoi.
Kohta 3 kertoo, että invariantti pätee myös rivin 4 lopussa.
Rivin 4 lopusta joudutaan uudelleen rivin 1 alkuun, joten kun rivin 1 alussa
ollaan kolmannen kerran, niin invariantti pätee.
Samalla tavalla voidaan päätellä, että kun rivin 1 alussa ollaan
neljännen, viidennen, kuudennen jne. kerran, niin
invariantti pätee.
Siis invariantti pätee aina kun suoritus on rivin 1 alussa.
Valitsemme invariantiksi väitteen ”`s` on `n`:n ja `m`:n suurin yhteinen
tekijä”.
Mieti ensin itse miksi kohta 2 pätee, ja katso sitten opettajan selitys
tästä.Pitää osoittaa, että kun ollaan
silmukan alussa, niin `s` on `n`:n ja `m`:n suurin yhteinen tekijä.
Tämä seuraa välittömästi siitä, minkä merkityksen annoimme aikaisemmin
symbolille `s`.
Mehän päätimme, että se on nimi alkuperäisten `n`:n ja `m`:n suurimmalle
yhteiselle tekijälle.
Tehtävänä on osoittaa, että jos rivin 2 alussa `s` on `n`:n ja `m`:n
suurin yhteinen tekijä, niin myös rivin 4 lopussa `s` on `n`:n ja `m`:n suurin
yhteinen tekijä.
Apuna saa käyttää tietoa `m != 0`.
Jokainen `n`:n ja `m`:n yhteinen tekijä on myös `N`:n tekijä, koska
…`n`:n ja `m`:n yhteinen tekijä on
`m`:n tekijä ja `N=m`.
Näistä yhteensä seuraa, että `n`:n ja `m`:n suurin yhteinen tekijä on myös
`N`:n ja `M`:n yhteinen tekijä.
Vielä tarvitsee osoittaa, että se on `N`:n ja `M`:n yhteisistä tekijöistä
suurin.
Teemme sen osoittamalla, että jokainen `N`:n ja `M`:n yhteinen tekijä on myös
`n`:n ja `m`:n tekijä.
Kun saamme sen tehtyä, on osoitettu, että `n`:n ja `m`:n yhteiset tekijät ovat
samat kuin `N`:n ja `M`:n yhteiset tekijät, jolloin toisen parin suurin on
myös toisen parin suurin.
Jokainen `N`:n ja `M`:n yhteinen tekijä on myös `m`:n tekijä, koska
…`N`:n ja `M`:n yhteinen tekijä on
`N`:n tekijä ja `N=m`.
Tarvittiinko tietoa `m != 0` mihinkään?Kyllä.
Aputulokset D ja E vaativat, että `J != 0`.
Koska `J`:n roolissa oli `m`, tarvittiin `m != 0`.
Pitää todistaa, että jos invariantti pätee ja `m != 0` ei päde, niin
`n=s`.
Tämä on melko helppoa.Koska `m != 0` ei
päde, pätee `m=0`.
Koska invariantti pätee, on `s` lukujen `n` ja 0 suurin yhteinen tekijä.
Ei voi olla `n=0`, koska muutoin `n`:llä ja nollalla ei olisi suurinta
yhteistä tekijää, mikä olisi vastoin sitä tietoa, että `s` on niiden suurin
yhteinen tekijä.
Siksi `n` on itsensä suurin tekijä.
Koska jokainen kokonaisluku on nollan tekijä, on `n` nollan tekijä.
Niinpä lukujen `n` ja 0 suurin yhteinen tekijä on `n`.
Siksi `s=n`.
Eukleideen versio
Eukleideen versio oli tällainen:
while `m != 0` do
`k` := maksimi`(n,m)`
`m` := minimi`(n,m)`
`n` := `k-m`
Siis modulo-operaatio oli korvattu sillä, että suuremmasta vähennettiin
pienempi.
Miten se käyttäytyy, kun aluksi `n=49` ja `m=70`?
Miten se käyttäytyy, kun aluksi `n=1000` ja `m=1`?
Tutkimme vain jonkin matkaa alkua.
Eukleideen versio toimii joillakin syötteillä nopeasti (kokeile vaikka
`m=n=1000`), mutta on olemassa loputtomasti syötteitä, joilla se toimii
hitaasti (esimerkiksi aina kun `n` on iso ja `m=1`).
Moderni SYT-algoritmi ei ole millään syötteellä todella hidas.
Sen nopeuden tutkiminen on oman tehtävänsä arvoinen asia.