Prolog (od francuskiego Programmation en Logique) jest to jeden z najpopularniejszych języków programowania logicznego. Prolog powstał jako język programowania służący do automatycznej analizy języków naturalnych, jest jednak językiem ogólnego zastosowania, szczególnie dobrze sprawdzającym się w programach związanych ze sztuczną inteligencją. Prolog w przeciwieństwie do większości popularnych języków jest językiem deklaratywnym.
Program w Prologu składa się z faktów oraz reguł wnioskowania. Aby go uruchomić trzeba przeistoczenie odpowiednie zapytanie.
Prolog stał się zbudowany w 1971 roku przez Alaina Colmeraurera oraz Phillipe'a Roussela.
Prolog ma za podstawę o rachunek predykatowy pierwszego rzędu, jednak ogranicza się tylko do klauzul Horna. Istnieją jednak wbudowane predykaty wyższego rzędu.
Fakty
W Prologu głosi się bazę faktów oraz reguł. Potem da się wykonywać zapytania na tej bazie. Podstawową jednostką w Prologu jest predykat. Predykat składa się z nagłówka oraz argumentów, na przykład: ojciec(tomasz, agata), gdzie ojciec to nagłówek a tomasz oraz agata to argumenty. Predykat może zostać użyty do wyrażenia pewnych faktów o świecie, które są znane programowi. W tym przypadku programista musi nadać im znaczenie. Jedną z interpretacji zdania ojciec(tomasz, agata) jest "tomasz to ojciec agaty". Jednak równie dobrze mogłoby to znaczyć "ojcem tomasza jest agata". Prolog nie ma pojęcia, co oznaczają te stwierdzenia. Wszystko co robi to manipulacja symbolami w oparciu o reguły. Dlatego da się wybrać dowolny sposób zapisu tego, że "tomasz to ojciec agaty", pod warunkiem konsekwentnego przestrzegania kolejności argumentów w całym programie.
Pewne predykaty potrafią oprócz wyrażania faktów posiadać skutki uboczne, jak dla przykładu wbudowany predykat
write('Cześć').
który wypisuje na ekranie 'Cześć'.
Reguły
Baza danych Prologu może też zawierać reguły. Przykład reguły to:
jest(światło) :- włączony(przycisk).
Zapis :- oznacza "wtedy, gdy" albo "jeśli". Ta reguła oznacza, że zdanie jest(światło) jest prawdziwe wtedy, kiedy prawdziwe jest zdanie włączony(przycisk). Reguły potrafią używać zmiennych. Zmienne zapisuje się zaczynając od wielkiej litery, dla odróżnienia od stałych, zaczynających się z małej. Na przykład:
ojciec(X, Y) :- rodzic(X, Y), jest_rodzaju_męskiego(X).
To oznacza: "dla każdych X oraz Y, jeśli rodzic(X,Y) oraz jest_rodzaju_męskiego(X) to ojciec(X, Y). Przesłanka oraz wniosek są zapisane w odwrotnej kolejności niż zwykle w logice. Co więcej, reguły muszą posiadać predykat jako wniosek. Można umieścić wiele predykatów we wniosku, połączonych koniunkcją, na przykład:
a,b,c :- d.
ale oznacza to tyle samo, co trzy oddzielne reguły:
a :- d.
b :- d.
c :- d.
Nie da się napisać reguły "a;b :- c", czyli "jeśli c to (a albo b)". Wynika to z ograniczenia zapisu do klauzul Horna.
Przykłady
Operacje na listach
% list_member(X,Y) = X trzeba do listy Y
% reimplementacja standardowego member(X,Y)
list_member(X, [X|_]).
list_member(X, [_|Y]) :-
list_member(X, Y).
% list_append(X,Y,Z) = Z powstaje ze sklejenia X oraz Y
% reimplementacja standardowego append(X,Y,Z)
list_append([], X, X).
list_append([H|T], X, [H|Y]) :-
list_append(T, X, Y).
% suma_elementow_listy(Lista, N) = N jest sumą elementów należących do Listy
suma_elementow_listy([], 0).
suma_elementow_listy([H|T], Wynik) :-
suma_elementow_listy(T, Tmp),
Wynik is H+Tmp.
% jak wyżej, lecz z użyciem rekurencji prawostronnej
suma_elementow_listy_tail(Lista, Wynik) :-
suma_elementow_listy_tail(Lista, 0, Wynik).
suma_elementow_listy_tail([], Wynik, Wynik).
suma_elementow_listy_tail([H|T], Akumulator, Wynik) :-
Akumulator2 is H+Akumulator, suma_elementow_listy_tail(T, Akumulator2, Wynik).
Sprawdź też
Linki zewnętrzne