Opiskelumateriaali - Logiikkaohjelmointi - Noppa

Ari Vesanen, Tietojenkäsittelytieteiden laitos, Oulun
yliopisto
815338A Ohjelmointikielten periaatteet: Logiikkaohjelmointi
Logiikkaohjelmointi
Tässä osassa käsitellään toista deklaratiivisen ohjelmoinnin paradigmaa eli
logiikkaohjelmointia. Pääasiallisena lähteenä on käytetty Sebestan ([Seb]) lukua 16.
Maarit Harsun teoksen [Har] luvussa 14 perehdytään myös logiikkaohjelmointiin.
Symboliseen logiikkaan perustuvaa ohjelmointia nimitetään logiikkaohjelmoinniksi ja
tällaiseen ohjelmointiin soveltuvia kieliä logiikkaohjelmointikieliksi. Joissakin
yhteyksissä nimitys deklaratiivinen kieli rajataan koskemaan pelkästään
logiikkaohjelmointikieliä. Logiikkaohjelmointikielen syntaksi ja semantiikka eroaa
imperatiivisen ohjelmointikielen vastaavista vielä voimakkaammin kuin
funktionaalisten kielten. Logiikkaohjelmoinnissa ohjelmoija ei määrittele ratkaisuun
johtavia toimenpiteitä, vaan ratkaisuun johtavia ominaisuuksia eli väittämiä, joiden
oikeellisuuden ohjelma pyrkii päättelemään vertailemalla niitä tunnettuihin
tosiasioihin. Tulos true merkitsee, että väittämä on oikea, mutta false merkitsee
yleensä vain, että väittämää ei pystytty todistamaan oikeaksi. Ihannetapauksessa
ohjelmoijan ei tarvitse keskittyä ratkaisuun johtavien toimenpiteiden ohjelmoimiseen
vaan ratkaisun löytämisen logiikkaan.
1. Symbolisesta logiikasta
Koska logiikkaohjelmointi perustuu vahvasti symbolisen logiikan käyttöön, tarkastellaan
hieman sen ominaisuuksia. Diskreettien rakenteiden kurssissa käsitellään myös
propositio- ja predikaattilogiikkaa (ks. [Kor], Luku 3). Propositio on looginen väittämä,
jolla on totuusarvo. Symbolinen logiikka yksinkertaisimmillaan on propositio- eli
lauselogiikkaa. Symbolisen logiikan avulla esitetään propositioiden välisiä suhteita ja
johdetaan uusia väittämiä olemassa olevista. Propositiosymboleita (joilla usein on
jokin tulkinta, esimerkiksi "On kylmä" tai "Sataa") yhdistellään käyttämällä loogisia
konnektiiveja; nämä ovat
Ari Vesanen, Tietojenkäsittelytieteiden laitos, Oulun
yliopisto
815338A Ohjelmointikielten periaatteet: Logiikkaohjelmointi
Nimi
Symboli
Esimerkki
Semantiikka
Negaatio
¬
¬a
ei a
Konjunktio
∧
a∧b
a ja b
Disjunktio
∨
a∨b
a tai b
Implikaatio
→ tai ←
a→b
a:sta seuraa b
a←b
b:stä seuraa a
a↔b
a ja b yhtäpitävät
Ekvivalenssi
↔
Propositiologiikassa negaatiolla on korkein preferenssi, minkä jälkeen tulevat
konjunktio, disjunktio ja ekvivalenssi, jotka ovat preferenssiltään korkeammalla kuin
implikaatio. Päättely-operaattoreiden = > ja < = > avulla voidaan muodostaa
päättelyketjuja, joiden avulla saadaan uusia lauseita esimerkiksi seuraavasti:
On kylmä → Palelee
On kylmä
______________________________________
=>
Palelee
Logiikkaohjelmoinnissa tarvittava symbolinen logiikka on predikaattilogiikkaa, jota
kuvataan hieman seuraavaksi. Itse asiassa logiikkaohjelmoinnin käyttämä logiikka on
jossakin propositio- ja predikaattilogiikan välimaastossa. Propositiologiikka ei sisällä
muuttujia, joten se on liian yksinkertaista, predikaattilogiikka taas on ratkeamaton, ts.
ei ole tehokasta algoritmia, jonka avulla voitaisiin päätellä onko jokin predikaatti tosi.
Predikaattilogiikan avulla voidaan muodostaa ilmauksia, jotka koskevat
propositiojoukkoja. Tätä varten loogisten lauseiden esittämisessä sallitaan lisäksi
muuttujat, jotka esiintyvät aina kvanttoreiden ∀ (universaalikvanttori) ja ∃
Ari Vesanen, Tietojenkäsittelytieteiden laitos, Oulun
yliopisto
815338A Ohjelmointikielten periaatteet: Logiikkaohjelmointi
(eksistenssikvanttori) yhteydessä. Ensin mainittu tarkoittaa, että jokin ominaisuus
pätee kaikilla arvoilla ja toinen, että on olemassa jokin arvo, jolle ominaisuus pätee, ts.
∀ Y:P
∃ Z:Q
Kaikilla arvoilla Y P on tosi
On olemassa sellainen Z että Q on tosi
Presedenssijärjestyksessä kvanttorit ovat samalla tasolla kuin negaatio. Propositio on
suljettu lause ja predikaatti on avoin lause, joka saadaan parametrisoimalla propositio.
Predikaatista saadaan propositio korvaamalla parametrit eli muuttujat joillakin
vakioilla. Predikaattilogiikan perusosat ovat:







Vakiot, jotka edustavat tunnettuja alkioita. Vakioita merkitään yleensä pienillä
kirjaimilla alkavilla tunnisteilla; lisäksi kokonaisluvut ovat vakioita.
Muuttujat, jotka edustavat tuntemattomia alkioita. Niitä merkitään yleensä
isoilla kirjaimilla alkavilla tunnisteilla.
Funktiosymbolit eli funktorit (nimeävät funktioita).
Predikaattisymbolit eli predikaatit, jotka määrittelevät alkioiden väliset relaatiot.
Esimerkiksi ">": p(X,Y)= X > Y.
Termit ovat lausekkeita jotka koostuvat vakioista, muuttujista ja funktoreista.
Esimerkiksi f(X) + Y + 10.
Atomikaava koostuu predikaatista, jonka argumenttina voi olla termi.
Esimerkiksi f(Z)-X < 0.
Kaava saadaan yhdistelemällä atomikaavoja loogisilla konnektiiveilla ja
kvanttoreillla.
Esimerkiksi ∃ Y ∀ X: (f(X) < 1) ∧ (Y > 0)
Loogisella päättelyllä tarkoitetaan johtopäätösten muodostamista premisseistä
(tunnetuista lauseista) loogisten päättelysääntöjen nojalla. Formaalisti oikea päättely
tapahtuu siten, että kaavojen tai lauseiden semantiikka esitetään formaalisti ja
noudatetaan korrektia semantiikkaa kussakin päättelysäännössä. Johtopäätökset
vastaavat (yleensä) ihmisen käsitystä loogisista seurauksista.
Ari Vesanen, Tietojenkäsittelytieteiden laitos, Oulun
yliopisto
815338A Ohjelmointikielten periaatteet: Logiikkaohjelmointi
Yksinkertaisimmat lauseet, joita käytetään logiikkaohjelmoinnissa, ovat atomisia
propositioita, nämä koostuvat yhdistetyistä termeistä, jotka kirjoitetaan
funktiokutsumaisessa muodossa. Yhdistetty termi muodostuu kahdesta osasta;
funktorista ja järjestetystä parametrien listasta, esimerkiksi
lammas(dolly)
syö(dolly,ruoho)
ovat yhdistettyjä termejä. Tässä esitetään ainoastaan, että relaatio lammas sisältää
alkion {dolly} ja että relaatio syö sisältää järjestetyn kaksikon {dolly,ruoho}. Lauseiden
semantiikka on deklaratiivista, ts. se on välittömästi nähtävissä lauseesta itsestään.
Mitään tulkintaa lauseisiin ei kuitenkaan sinänsä sisälly. Esimerkiksi jälkimmäinen termi
voi tarkoittaa, että dolly syö ruohoa, ruoho syö dollyä tai lause voi tarkoittaa jotakin
aivan muuta. Ylläesitetyt lauseet koostuvat vakioista, mutta propositioissa voi myös
esiintyä muuttujia. Atomisten propositioiden ja konnektiivien avulla voidaan
muodostaa koottuja propositioita, esimerkiksi
lammas(dolly) → nisäkäs(dolly)
syö(dolly,X) ∧ liha(X)
Jotta logiikkaohjelmointi olisi lainkaan hyödyllistä, siinä täytyy olla jonkinlaisia
mekanismeja, joiden avulla johdetaan uusia sääntöjä. Sääntö voidaan johtaa annetuista
tosista lauseista soveltamalla niihin äärellistä määrää peräkkäisiä päättelyjä.
Logiikkaohjelmoinnissa päättelymekanismit perustuvat modus ponens- sääntöön ja
universaalikvanttorin eliminointiin.
Modus ponens:
Lause A ∧ (A → B) voidaan korvata termillä B
Universaalikvanttorin eliminoimissääntö:
Lause ∀ X:A(X) voidaan korvata lauseella, jossa kaikki muuttujan
X vapaat esiintymät on korvattu jollakin termillä.
Ari Vesanen, Tietojenkäsittelytieteiden laitos, Oulun
yliopisto
815338A Ohjelmointikielten periaatteet: Logiikkaohjelmointi
Koneellisessa loogisessa päättelyssä suureksi ongelmaksi muodostuu keskenään
ekvivalenttien lauseiden joukko, joka on kooltaan valtava. Siksi olisi toivottavaa
määritellä jokin standardimuoto, jonka avulla propositiot voitaisiin esittää. Eräs
tällainen on klausuuli. Klausuulin muoto on
B1 ∨ B2 ∨ ...∨ BN ← A1 ∧ A2 ... ∧ AM
Missä A:t ja B:t ovat termejä. Klausuulin semantiikka: Jos kaikki A:t ovat tosia, ainakin
yksi B on tosi. Oikeaa puolta kutsutaan edellytykseksi (antecedent) ja vasenta puolta
seuraukseksi (consequent). Vasen puoli toteutuu, kunhan vain oikea puoli voidaan
osoittaa todeksi. Voidaan osoittaa, että kaikki predikaattilogiikan propositiot on
algoritmisesti mahdollista muuttaa klausuuleiksi. Logiikkaohjelmoinnissa käytetään
yleisesti erikoistapausta
B ← A1 ∧ A2 ... ∧ AM
jota kutsutaan Hornin klausuuliksi. Esimerkiksi
syö(dolly,timotei) ← syö(dolly,ruoho)∧ ruoho(timotei)
Mikäli Hornin klausuuli käsittää ainoastaan seurauksen (oikea puoli on tyhjä), sen vasen
puoli on varauksetta tosi. Joskus tällaisia klausuuleja sanotaan myös faktoiksi.
Alan Robinson kehitti vuonna 1965 ns. resoluutioperiaatteen tutkiessaan
mahdollisuuksia automatisoida lauseiden todistusmekanismeja. Resoluutio on
päättelymekanismi, jonka avulla annetuista propositioista johdetaan uusia
propositioita. Resoluutioaskeleen periaate on hyvin yksinkertainen ja se perustuu
modus ponens-eliminointisääntöön. Oletetaan esimerkiksi, että seuraavat säännöt ovat
voimassa:
P ← Q (1)
R ← P (2)
Tästä saadaan johdettua sääntö
Ari Vesanen, Tietojenkäsittelytieteiden laitos, Oulun
yliopisto
815338A Ohjelmointikielten periaatteet: Logiikkaohjelmointi
R ← Q (3)
Ensimmäisistä klausuuleista voidaan päätellä eräänlainen supistamismekanismi:
kirjoitetaan
P ∧ R ← Q ∧ P
Ja "supistetaan" P pois, jolloin jäljelle jää klausuuli (3). Logiikkaohjelmoinnissa
resoluutiomekanismissa joudutaan vielä huomioimaan muuttujat ja käyttämään lisäksi
universaalikvanttorin eliminointisääntöä.
Resoluutio yleistyy myös Hornin klausuuleille, joissa oikealla puolella on useampi termi.
Resoluutiomekanismin käyttö logiikkaohjelmassa toimii seuraavasti: Kun halutaan
todistaa jokin väite, se esitetään Hornin klausuulin oikeana puolena. Klausuuli
yhdistetään tunnettuihin sääntöihin ja mikäli onnistutaan resoluution avulla
saavuttamaan tyhjä klausuuli, on väite tosi. Väitettä voidaan myös nimittää kyselyksi
(query).
Esimerkki. Oletetaan säännöt
(1)
(2)
(3)
(4)
jalat(x,2) ← nisäkäs(x) ∧ kädet(x,2)
jalat(x,4) ← nisäkäs(x) ∧ kädet(x,0)
nisäkäs(lammas) ←
kädet(lammas,0) ←
Halutaan todistaa väite
jalat(lammas,4)
Aluksi kirjoitetaan väite Hornin klausuulin oikeana puolena
←
jalat(lammas,4)
Yhdistetään tämä sääntöön (2), jolloin saadaan
Ari Vesanen, Tietojenkäsittelytieteiden laitos, Oulun
yliopisto
815338A Ohjelmointikielten periaatteet: Logiikkaohjelmointi
jalat(x,4) ← nisäkäs(x) ∧ kädet(x,0) ∧ jalat(lammas,4)
Korvataan x vakiolla lammas:
jalat(lammas,4) ← nisäkäs(lammas) ∧ kädet(lammas,0) ∧ jalat(lammas,4)
Resoluutiolla saadaan supistettua jalat(lammas,4) pois, joten tullaan lausekkeeseen
← nisäkäs(lammas) ∧ kädet(lammas,0)
Yhdistetään tämä sääntöön (3):
nisäkäs(lammas) ← nisäkäs(lammas) ∧ kädet(lammas,0)
Resoluutiolla saadaan supistettua nisäkäs(lammas) pois ja lauseke saadaan muotoon
← kädet(lammas,0)
Yhdistetään lopuksi tämä neljänteen sääntöön ja käytetään taas resoluutiota
supistamaan kädet(lammas,0) pois:
kädet(lammas,0) ← kädet(lammas,0)
←
Päästiin siis tyhjään klausuuliin, joten väite on tosi.
Ari Vesanen, Tietojenkäsittelytieteiden laitos, Oulun
yliopisto
815338A Ohjelmointikielten periaatteet: Logiikkaohjelmointi
2. Prolog
Tarkastellaan yleisimmän logiikkaohjelmointikielen Prologin ominaisuuksia. Prologin
perusrakenteen suunnittelivat Colmerauer, Roussel sekä Kowalski, ja ensimmäinen
Prolog-tulkki implementoitiin Marseillessa vuonna 1972. Kielestä on syntynyt monia
murteita, joilla voi olla hyvinkin erilaiset syntaksit. Edinburghin yliopistossa luotu versio
on kuitenkin saavuttanut jonkinlaisen standardin aseman. Kielelle on laadittu vuonna
1995 ISO-standardi, joka pohjautuu Edinburghin versioon. Prolog ei ole puhtaasti
logiikkaohjelmointikieli, vaan sisältää piirteitä myös imperatiivisista ohjelmointikielistä.
Prologin ominaisuuksia kuvataan tässä lähinnä Loudenin ([Lou], kappale 11) ja Sebestan
([Seb], kappaleet 16.5 – 16.7) mukaisesti.
Prologissa käytetään samankaltaista notaatiota Hornin klausuuleille kuin yllä on
esitetty, mutta nuolimerkintä ← on korvattu merkinnällä :- ja and -merkintä pilkulla, ts.
Prologissa kirjoitettaisiin
esi_isa(X,Y) :- vanhempi(X,Z), esi_isa(Z,Y).
Prologissa erotetaan muuttujien ja vakioiden sekä predikaattien nimet siten, että
muuttujien nimet alkavat isolla kirjaimella. Muuten alkukirjaimena käytetään pientä
kirjainta. Prologin jokainen lause päättyy pisteeseen.
Prologissa peruslauseista muodostuu oletetun tiedon tietokanta, jota hyväksi käyttäen
voidaan johtaa uutta tietoa. Prologissa käytetään kahdentyyppisiä peruslauseita:
Lauseet, jotka vastaavat Hornin klausuulien vasenta puolta ja lauseet jotka vastaavat
varsinaisia Hornin klausuuleja. Ensin mainitut katsotaan faktoiksi, ts. loogisesti ne
tulkitaan tosiksi lauseiksi. Toisen tyypin peruslauseita sanotaan myös säännöiksi.
Prologissa väitteitä, joita halutaan todistaa, kutsutaan kyselyiksi (query) tai
maalilauseiksi (goal) ja nämä esitetään Prolog -tulkille samassa muodossa kuin
faktatkin. Oletetaan, että tietokantaan on syötetty lauseet
esi_isa(X,Y) :- vanhempi(X,Z), esi_isa(Z,Y).
esi_isa(X,X).
vanhempi(nooa,haam).
Ari Vesanen, Tietojenkäsittelytieteiden laitos, Oulun
yliopisto
815338A Ohjelmointikielten periaatteet: Logiikkaohjelmointi
Tällöin kysely
esi_isa(nooa,haam)
tuottaa tuloksen yes (tai true) ja kysely
esi_isa(haam,nooa)
tuloksen no (tai false). Samoin voidaan tehdä kysely
esi_isa(X,haam)
jolloin vastauksena saadaan
X = nooa ->; (haetaan lisää)
X = haam
Prolog sisältää määrittelyt aritmeettisille operaatiolle ja niiden evaluoinnille. Prologille
on kuitenkin kerrottava, milloin aritmeettista lauseketta tarkastellaan lausekkeena ja
milloin se on evaluoitava. Esimerkiksi kirjoittamalla
write(5+6).
saa vastaukseksi 5+6. Mikäli haluaa Prologin evaluoivan summan, on kirjoitettava
esimerkiksi
X is 5+6, write(X).
jolloin saa vastaukseksi X=11. Tästä aiheutuu mm. se että aritmeettisten lausekkeiden
vertailu tuottaa tuloksen "no" mikäli lausekkeet ovat erilaiset siitä huolimatta, että
niiden arvot olisivat samat. Siten
3+5 = 5+3
antaa tuloksen no. Jos halutaan vertailla lausekkeita niiden arvon perusteella, voidaan
kirjoittaa predikaatti
Ari Vesanen, Tietojenkäsittelytieteiden laitos, Oulun
yliopisto
815338A Ohjelmointikielten periaatteet: Logiikkaohjelmointi
sama_arvo(Termi1,Termi2) :- X is Termi1, Y is Termi2, X=Y.
Tällöin syöttämällä
sama_arvo(3+5,5+3)
saadaan tulokseksi yes.
Instantiointi tarkoittaa tyypin ja arvon liittämistä muuttujaan. Liittämisellä
(unification) tarkoitetaan Prologissa prosessia, jolla kaksi muuttujaa instantioidaan sillä
tavoin, että muuttujat täsmäävät resoluutiossa. Näin ollen liittäminen tarkoittaa
jossakin mielessä kahden termin tekemistä samoiksi. Liittäminen ilmaistaan
yhtäsuuruudella, esimerkiksi
a = a
-> yes (liittäminen onnistui)
a = b
-> no (eri vakioiden liittäminen ei onnistu)
a = X
-> X = a (muuttuja, jota ei ole instantioitu, liittyy mihin tahansa ja
instantioituu tällä)
f(a,Z) = f(Y,b)
-> Z = b
-> Y = a (liittäminen onnistuu kun Z=b ja Y = a)
f(X) = g(X)
-> no (kahden eri funktion liittäminen ei onnistu)
Tarkastellaan seuraavaksi resoluution mekanismia Prologissa, ts. minkälaista
hakustrategiaa käytetään johdettaessa tulosta. Resoluutiota sovelletaan täysin
lineaarisesti siten, että maaleja korvataan vasemmalta oikealle ja tietokannan
klausuuleja käydään läpi ylhäältä alaspäin. Alimaalit tarkastellaan välittömästi, kun ne
Ari Vesanen, Tietojenkäsittelytieteiden laitos, Oulun
yliopisto
815338A Ohjelmointikielten periaatteet: Logiikkaohjelmointi
on määrätty. Tällaista strategiaa sanotaan syvyyssuntaiseksi (depth-first). Palataan
aiempaan esimerkkiin
esi_isa(X,Y) :- vanhempi(X,Z), esi_isa(Z,Y).
esi_isa(X,X).
vanhempi(nooa,haam).
Olkoon annettu maali
esi_isa(X,haam).
Tällöin alimaalit muodostavat seuraavan hakupuun:
Prolog palauttaa ensimmäisen vastaantulevan ratkaisun ja mikäli ratkaisuja halutaan
lisää, puussa peräydytään (backtrack), kunnes löydetään uusia haaroja joita voidaan
kulkea. Tämän kaltainen hakustrategia on tehokas, mutta kärsii samasta ongelmasta
Ari Vesanen, Tietojenkäsittelytieteiden laitos, Oulun
yliopisto
815338A Ohjelmointikielten periaatteet: Logiikkaohjelmointi
kuin rekursiivisesti laskeutuva jäsentäjä: säännöissä ei saa olla vasemmanpuoleista
rekursiota. Jos ensimmäinen sääntö olisi kirjoitettu
esi_isa(X,Y) :- esi_isa(Z,Y), vanhempi(X,Z).
Prolog joutuisi ikuiseen silmukkaan maalin johdossa yrittäessään toteuttaa lauseen
esi_isa(Z,Y) soveltamalla toistuvasti ensimmäistä lausetta.
Prologin peräytymismekanismia voidaan käyttää silmukoiden ja toistuvien hakujen
toteuttamiseen, kunhan vain jotenkin pakotetaan etsinnän jatkaminen, vaikka ratkaisu
löytyykin. Tätä varten Prologissa on predikaatti fail. Lisäksi haku voidaan katkaista
operaattorilla !, joten ikuiset hakuprosessit voidaan ehkäistä. Tässä ei perehdytä näiden
mekanismien yksityiskohtiin.
Tarkastellaan vielä Prologin listarakenteita, jotka ovat Prolog-ohjelmoinnissa
keskeisessä asemassa. Prologissa listaa merkitään hakasulkeilla, joiden sisällä ovat
listan alkiot pilkulla erotettuna (esimerkiksi [a,b,c]), joten syntaksiltaan Prologin listat
muistuttavat Haskellin listoja. Merkintä [] tarkoittaa tyhjää listaa. Prologissa ei ole
listojen muodostamiseen ja purkamiseen erillisiä funktioita; sen sijaan kielessä
käytetään merkintää [H|T] tarkoittamaan listaa, jonka pää on H ja häntä T. Prologin
listojen muodostamisen perusoperaatioita on append, joka liittää listoja yhteen,
esimerkiksi
?- Lista = [eka, toka, kolmas].
Lista = [eka, toka, kolmas].
?- append($Lista,[nelj],Klista).
Klista = [eka, toka, kolmas, nelj].
Ari Vesanen, Tietojenkäsittelytieteiden laitos, Oulun
yliopisto
815338A Ohjelmointikielten periaatteet: Logiikkaohjelmointi
Prologin append-operaatiota voidaan soveltaa myös päättelemään, minkä listojen
yhdistäminen antaa tuloslistan:
?- append(X,Y,$Lista).
X = [],
Y = [eka, toka, kolmas];
X = [eka],
Y = [toka, kolmas];
X = [eka, toka],
Y = [kolmas];
X = [eka, toka, kolmas],
Y = [];
Esitetään vielä, miten listan kääntämisoperaatio voidaan toteuttaa Prologilla:
kaanna([],[]).
kaanna([H|T],K) :kaanna(T,K1),append(K1,[H],K).
Tyhjän listan kääntäminen tuottaa tyhjän listan. Kun operaatiota sovelletaan
epätyhjään listaan, käännetään ensin listan häntä, muodostetaan siitä lista K1 ja
lisätään alkuun listan pää.
Lopuksi käsitellään Prologin puutteita, jotka ainakin jossakin määrin koskevat yleisesti
logiikkaohjelmointikieliä. Logiikkaohjelmointikielten piti alun perin muuttaa ohjelmointi
spesifioinniksi ja vapauttaa ohjelmoija ratkaisun ohjelmoinnin yksityiskohdista. Tähän
on pystytty vain osittain ja logiikkakielten päättelyissään käyttämät algoritmit ovat
tuoneet omia ongelmia näillä kielillä ohjelmointiin. Esimerkiksi Prologin
liittämisalgoritmi on itse asiassa epäkorrekti, tietyt määrittelyt johtavat sen ikuisiin
silmukoihin (ks. [Lou], 11.5.1.). Prologissa on käytetty yksinkertaista ja tehokasta
algoritmia, joka ei toimi oikein kaikissa erikoistapauksissa; tehokkaat ja korrektit
algoritmit ovat huomattavasti monimutkaisempia.
Looginen negaatio muodostuu ongelmalliseksi käsitteeksi logiikkakielissä niiden
"suljetun maailman" oletuksen vuoksi. Logiikkakieli pitää väitettä vääränä, ellei sitä
voida johtaa annetuista lauseista. Näin ollen väitteen negaatio on tosi, ellei väitettä
Ari Vesanen, Tietojenkäsittelytieteiden laitos, Oulun
yliopisto
815338A Ohjelmointikielten periaatteet: Logiikkaohjelmointi
voida johtaa. Siten negaatio tarkoittaa pikemminkin epäonnistumista kuin loogista
epätotuutta ja voi johtaa omalaatuisiin tuloksiin.
Tietyssä mielessä myös logiikkaohjelmoinnin perimmäinen idea ratkaisun
spesifioinnista sen tarkkojen yksityiskohtien ohjelmoimisen sijaan on ongelmallinen.
Esimerkiksi lajitteluohjelman kirjoittaminen luonnollisimmalla tavalla johtaa listan
kaikkien mahdollisten permutaatioiden generoimiseen, kunnes tavataan sellainen
permutaatio, että lista on järjestyksessä. Tämä on luonnollisesti äärettömän tehoton
tapa lajitella eikä sovellu käytännön ohjelmiin. Näin ollen ohjelmoijan on kuitenkin
ohjelmoitava jokin konkreettinen lajittelualgoritmi ja logiikkaohjelmointi lähenee
perinteisempiä ohjelmointimenetelmiä. (Prologilla voidaan kyllä esimerkiksi Quicksort algoritmi kirjoittaa varsin näppärästi).
Logiikkakielten pääasialliset sovelluskohteet liittyvät tekoälyyn tavalla tai toisella,
kielissä on sovellettu mm. luonnollisen kielen käsittelyyn ja asiantuntijajärjestelmien
toteuttamiseen. Tekoälysovellusten ulkopuolella logiikkaohjelmointikieliä on käytetty
toistaiseksi varsin vähän, mutta relaatiotietokantojen käsittelyyn niitä on ainakin
sovellettu.
Lähteet
[Har] Harsu, Maarit. Ohjelmointikielet, Periaatteet, käsitteet, valintaperusteet,
Talentum 2005.
[Kor] Kortelainen, Juha. Diskreetit rakenteet 811120P, Luentomoniste.
(https://noppa.oulu.fi/noppa/kurssi/811120p/materiaali/811120P_luennot_2.pdf).
[Lou] Louden, Kenneth C. Programming Languages, Principles and Practice, PWS-KENT
1993.
[Seb] Sebesta, Robert W. Concepts of Programming Languages 10th edition, Pearson
2013.