PLO-LAB
1
-
Środowisko SICStus Prologu (tryby pracy, zmienne a
stałe, składnia).
-
Proste fakty i klauzule typu: dziecko(jan, adam).
-
Zadawanie zapytań ze stałymi oraz ze zmiennymi.
Prolog jest językiem programowania deklaratywnego. Jest oparty na logice 1-szego rzędu i korzysta z mechanizmu uzgadniania i automatycznego nawracania.
Rozważmy, na przykład, następujący program:
polaczone(X,
Y) :- krawedz(X, Y).
polaczone(X,
Y) :- polaczone(X, Z), krawedz(Z, Y).
krawedz(a,
b).
krawedz(b,
c).
krawedz(c,
d).
Ten program zawiera fakty określające relację „krawędź” oraz 2 klauzule definiujące predykat „połączone”. Klauzule definiujące predykaty są odczytane w stylu zstępującym. Np. X jest połączony z Y jeśli istnieje krawędź z X do Y lub X jest połączony z pewnym wierzchołkiem Z i istnieje krawędź z Z do Y.
Z tego przykładu, widać, że:
- nazwy predykatów i stałych zaczynają się od małych liter (lub podkreślenia),
- nazwy zmiennych zaczynają się od dużych liter,
- każda klauzula zakończy się kropką.
Są różne implementacje prologu, np. SICStus Prolog, SWI-Prolog, MIM Prolog. Pierwsza implementacja jest sharewarem, a druga jest freewarem. Dokumentacja SICStus Prolog jest dostępna w Internecie (szukajmy googlem). Na serwerze students, można uruchomić SICStus Prolog poleceniem sicstus.
Po uruchamianiu sicstus, system działa w trybie wykonywania zapytań. Programy możemy edytować używając jakiegoś edytora tekstu i załadować do systemu (bywając w trybie wykonywania zapytań) poleceniem:
?-
consult(nazwa_pliku).
lub
?-
[nazwa_pliku].
Możemy przełączyć system z trybu zapytań na tryb definiowania procedur poleceniem:
?-
[user].
i można wtedy bezpośrednio wpisać program. Aby wyjść z trybu definiowania, należy nacisnąć Ctrl+D.
Jeśli chcemy wymienić tylko klauzule definiujące pewne predykaty, to zamiast consult używajmy reconsult. Te polecenia mogą przyjąć kilka argumentów (tzn. nazw kilku plików).
Zapytaniem jest formuła w Prologu. Najprostsze zapytanie ma postać atomu. Na przykład, poprzez zapytanie
?- krawedz(a,b).
chcemy zapytać czy jest krawędź z a do b. To zapytanie nie zawiera zmiennych. Zaś, poprzez
?- polaczone(a,X).
chcemy zapytać, z którymi wierzchołkami a jest połączony. Tu, X oznacza zmienną, dla której chcemy uzyskać odpowiedzi. System udziela pierwszą odpowiedź. Aby wyświetlić kolejną odpowiedź, należy wpisać średnik (zamiast enter).
Nieco bardziej złożone zapytanie możemy mieć na przykład:
?- polaczone(a,X), polaczone(X,d).
Przecinek tu oznacza boolowski operator „i”.
Aby
wyświetlić zawartość załadowanego programu możemy używać polecenia:
?- listing.
Jeśli chcemy
wyświetlić tylko klauzule definiujące pewien predykatu, używajmy:
?- listing(nazwa_predykatu).
Na przykład:
?- listing(polaczone).
Dodatkowe
uwagi o składni programów:
-
brak
deklaracji (zmiennych, stałych, ...)
-
komentarze
są w postaci: % ... lub /* ... */
-
zmienne
anominiowe ( _ )
Np. poprzez
?- krawedz(X,_).
chcemy zapytać o wierzchołki, z których wychodzi przynajmniej jedna krawędź.
Zadania
1)
Rozważ w/w program
przykładowy. Jeśli zadajemy zapytanie
?- polaczone(a,X).
i chcemy uzyskać odpowiedzi poprzez wpisanie kolejnych średników
to po trzech odpowiedziach dostaniemy komunikat „... insufficient memory”,
czyli „brakowało pamięci” bo program zapętla się. Jak zmodyfikować program aby
usunąć takie zjawisko?
2)
Zdefiniuj
predykat nastepniki(X), który wyświetli wszystkie wierzchołki Y do
których X jest połączony (czyli polaczone(X, Y) zachodzi). Można używać
predykatu fail, który zawsze się zawodzi, i predykatu write(W),
który wyświetli wyrażenie W. (Można
traktować fail jako predykat zdefiniowany pustym programem.)
3)
Czy program
napisany w punkcie 2 zwraca wynik „no”. Jeśli tak jest, to zmodyfikuj go, żeby
zwracał zawsze „yes” (czyli pozytywną odpowiedź).