Tässä tehtävässä todistetaan eräs nopea algoritmi oikein toimivaksi.
Tarkoituksena on harjoitella ohjelmista päättelemistä.
Algoritmi ja sen tehtävä
Taulukko A[1…n] on kasvavassa suuruusjärjestyksessä.
Oheisen algoritmin tehtävänä on löytää siitä kaksi alkiota, joiden summa on
x.
1 a := 1
2 y := n
3 whilea < y &&
A[a] + A[ y] ≠ xdo
4 ifA[a] + A[ y] <
x
5 thena := a + 1
6 elsey := y − 1
Huomaatko, että vaatimusmäärittelymme on hieman epätarkka?
Esimerkki syötteestä, jolla etsityt alkiot ovat toisen tulkinnan mukaan
olemassa ja toisen tulkinnan mukaan eivät ole, löytyy tästäA = [1, 3, 4] ja x =
6.
Vaatimusmäärittely on epätarkka sikäli, että …Tällaisissa tilanteissa ei aina ole selvää,
saavatko mainitut kaksi alkiota olla sama alkio.
Kun sanotaan ”kahden parittoman luvun summa on aina parillinen”, niin ne luvut
saavat olla sama luku.
Jos pyydät minua mainitsemaan kaksi eläintä, niin varmaankin hyväksyt
vastaukseksi ”koira ja kissa” mutta et hyväksy ”koira ja koira”.
Kirjoita seuraavat väitteet.
Käytämme jatkossa tulkintaa ”kaksi eri alkiota, jotka saavat olla
yhtäsuuret”.
Todistusmenetelmä
Siksi on tavallista käsitellä sellaiset erikoistapaukset
erikseen ja olettaa päätapauksen kohdalla, että ei olla niissä.
Toimiiko algoritmi oikein kun taulukko A[…] on tyhjä?
Perustele vastauksesi.
Open vastausKyllä toimii.
Kun taulukko on tyhjä, n = 0 eikä etsittyjä alkioita ole.
Algoritmi lopettaa heti saavuttuaan ensimmäisen kerran riville 3, ja
a:n ja y:n arvoista näkyy edellä mainitulla testillä
a < y, että niitä ei ole.
Saimme äsken yllä mainitulla oletuksella, että tämä1 ≤ a ≤ y ≤
n pätee aina kun suoritus on rivin 3 alussa.
Se takaa, että (olettaen, että lukualue ei lopu kesken) algoritmi ei koskaan
suorita mitään laitonta.
Miten se sen tekee?
…Se takaa, että taulukon A
indeksit ovat aina laillisia.
Muuta potentiaalisesti laitonta algoritmi ei tee (olettaen, että lukualue ei
lopu kesken).
Silmukan oikeaksi todistamisessa käytetään usein viisikohtaista menetelmää:
Osoitetaan, että se pätee kun silmukkaan tullaan silmukan edeltä.
Osoitetaan, että jos se ja silmukan ehto pätevät kun ollaan silmukan
alussa, niin se pätee myös kun ollaan uudelleen silmukan alussa.
Toisin sanoen osoitetaan, että silmukan kierros ei voi saada invarianttia pois
voimasta.
(Se saa olla tilapäisesti pois voimasta silmukan kierroksen ollessa kesken.)
Osoitetaan, että silmukkaa ei voida kiertää loputtomasti.
Osoitetaan, että jos invariantti pätee ja silmukan ehto ei päde, niin
silmukan lopputulokselta haluttu asia pätee.
Menetelmän kohta 4
Algoritmi lopettaa varmasti, koska …Jokaisella kierroksella y − a pienenee yhdellä, koska joko a kasvaa yhdellä ilman että y muuttuu, tai y
vähenee yhdellä ilman että a muuttuu.
Algoritmi lopettaa viimeistään kun y − a = 0.
Menetelmän kohta 1
Alamme nyt tutkia, miksi algoritmi löytää mitä pitääkin.
Algoritmin suunnittelija pyrki siihen, että jokainen ehdot täyttävä
alkiopari sijaitsee välillä a, …, y.
Tarkastamme kohta, onko tämä ominaisuus invariantti.
Sitä ennen kuitenkin kirjoitamme sen kaavana, koska tällä kurssilla nyt vaan
kerta kaikkiaan harjoitellaan kaavoja, koska niiden käyttö paljastaa piileviä
väärinymmärryksiä ajoissa.
Valitettavasti valmiiseen kaavaan tulisi niin paljon muuttujia, että
vastausten tarkastaminen kuormittaisi yliopiston palvelinta liikaa.
Siksi älä käytä alla muuttujaa x, vaan kirjoita sen sijaan 2.
Tästä eteenpäin kirjoita x:n paikalle x eikä 2.
Menetelmän kohta 2
Kun silmukkaan tullaan sen edeltä, äsken kirjoittamamme
invariantti on triviaalisti totta, koska …Silloin väli a, …, y kattaa koko taulukon, koska
a = 1 ja y = n.
Invariantin kaavassa tämä näkyy siten, että jokaisella i ja j, joilla pätee 1 ≤ i < j ≤ n, pätee myös a ≤
i < j ≤ y ja samalla koko kvantifioitu
osuus.
Menetelmän kohta 2 on valmis.
Menetelmän kohta 5
Menetelmän kohdassa 5 on osoitettava, että silmukan lopetettua joko
A[a] ja A[ y] muodostavat ehdot täyttävän
alkioparin tai sellaista ei ole olemassa.
Myös on osoitettava, että valinta näiden kahden väliltä määräytyy siitä,
päteekö a < y.
Jos silmukan lopetettua a < y, niin algoritmi lopetti siksi,
että …A[a] + A[ y] =
x.
Alkiot A[a] ja A[ y] ovat eri alkio, koska …a ≠ y koska a <
y.
Jos silmukan lopetettua ¬(a < y), niin …Välin a, …, y pituus on
enintään 1, joten väliin ei mahdu kahta eri alkiota.
Siksi ehdot täyttävää alkioparia ei ole olemassa.
Menetelmän kohta 3
Jäljellä on ominaisuus 3.
Silmukan vartalossa joko a kasvaa tai y vähenee, eikä tapahdu
muita muutoksia muuttujien arvoissa.
On osoitettava, että tämä ei voi poistaa invarianttia voimasta.
On osoitettava, että a:n arvo ennen kasvua ei voi olla ehdot
täyttävän alkioparin osapuoli.
On siis osoitettava, että ∀ j; 1 ≤ j ≤ n:
A[a] + A[ j] ≠ x.
Olemme osoittaneet, että A[a] ei voi muodostaa ehdot
täyttävää paria minkään alkion kanssa.
Siksi a:n voi jättää pois etsintäalueelta.
Miksi edellisessä kohdassa ei käytetty rivin 4 if-lauseen ehdon
A[a] + A[ y] < x negaatiota
A[a] + A[ y] ≥ x?
VastausKun
A[a] + A[ y] = x, niin riville 6 ei mennä,
koska ei mennä edes riville 4.
Loput A[i] eivät voi muodostaa ehdot täyttävää alkioparia
A[ y]:n kanssa, koska …Invariantti lupaa, että välillä 1, …, a − 1 sijaitsevat
alkiot eivät muodosta ehdot täyttävää paria minkään alkion kanssa, ja niin
ollen eivät alkion A[ y] kanssa.
Olemme osoittaneet, että y:n voi jättää pois etsintäalueelta.
Menetelmän kohta 3 ja samalla koko algoritmin todistus on valmis.