Lyhyt MathCheck-ohje (uuteen välilehteen)
Tässä tehtävässä todistetaan eräs nopea algoritmi oikein toimivaksi. Tarkoituksena on harjoitella ohjelmista päättelemistä.
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 while a < y && A[a] + A[ y] ≠ x do
4 if A[a] + A[ y] < x
5 then a := a + 1
6 else y := 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”.
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ää:
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.
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.
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 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.
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.