Toisen asteen logiikkaohjelmointi

Tähän asti on käsitelty niitä Prologin ominaisuuksia, jotka perustuvat puhtaasti ensimmäisen asteen predikaattilogiikkaan. Prologiin on kuitenkin sisällytetty myös ensimmäisen asteen predikaattilogiikan ulkopuolisia ominaisuuksia. Näitä piirteitä kutsutaan toiseksi asteeksi, koska ne käsittelevät joukkoja ja niiden ominaisuuksia eivätkä yksilöitä.

Käytännössä tämä tarkoittaa sitä, että ohjelmoija voi tehdä aiemmin kuvatun kaltaisen ensimmäisen asteen predikaattilogiikkaa käyttävän predikaatin, ja pyytää toisen asteen predikaattilogiikan avulla kaikkien predikaatin toteuttavien ratkaisujen joukon. Toisen asteen predikaatti on siis predikaatti, jonka saamista parametreista osa on toisia predikaatteja. Gprologin tarjoamia toisen asteen predikaatteja ovat findall/3, bagof/3 ja setof/3

Kirjoitetaan aluksi pieni ohjelmanpätkä, jossa on muutamia faktoja:


foo(1,5).
foo(1,3).
foo(2,4).
foo(2,3).
foo(2,8).
foo(2,8).

Kokeillaan toisen asteen predikaatteja tulkissa:

| ?- findall(Y,foo(X,Y),L).

L = [5,3,4,3,8,8]

yes
| ?- findall(Y,foo(5,Y),L).

L = []

yes

Predikaatti findall etsi kaikki ne X:n ja Y:n yhdistelmät, joilla predikaatti foo(X,Y) onnistuu ja sijoitti näin löydetyt Y:n arvot listaan L. Dublikaatteja se ei poistanut. Findall onnistuu aina tasan kerran. Jos ratkaisuja ei löydy, samaistetaan tuloslista tyhjään listaan.

| ?- bagof(Y,foo(X,Y),L).

L = [5,3]
X = 1 ? ;

L = [4,3,8,8]
X = 2

(10 ms) yes
| ?- bagof(Y,foo(5,Y),L). 

no

Predikaatti bagof sen sijaan onnistuu kerran jokaista uusia ratkaisuja tuottavaa X:n arvoa kohden, ja sijoittaa kyseistä X:n arvoa vastaavat ratkaisut Y:lle tuloslistaan. Jos yhtään ratkaisua ei löydy, bagof epäonnistuu.

| ?- setof(Y,foo(X,Y),L). 

L = [3,5]
X = 1 ? ;

L = [3,4,8]
X = 2

yes

Predikaatti setof toimii kuten bagof, mutta se järjestää tulosjoukot ja poistaa dublikaatit. Se toiminta on ekvivalenttia bagof:n ja sortin peräkkäisen suorituksen kanssa.

Toisen asteen predikaatteja voi luonnollisestikin soveltaa myös monimutkaisempiin predikaatteihin. Kokeillaanpa niitä vaikkapa jo aiemmin esiteltyyn ruokalista-esimerkkiin:

| ?- [ruokalista].         
compiling /home/ai/prolog_esimerkkeja/ruokalista.pl for byte code...
/home/ai/prolog_esimerkkeja/ruokalista.pl compiled, 58 lines read - 7196 bytes written, 92 ms

(10 ms) yes
| ?- setof(X,vegaani(X),L).

L = [kasvispaistos,purjoperunakeitto]

yes