Prolog 2 (Filip Wroński, Łukasz Betkowski, Paweł Świerblewski

Transkrypt

Prolog 2 (Filip Wroński, Łukasz Betkowski, Paweł Świerblewski
Prolog 2
(Filip Wroński, Łukasz Betkowski, Paweł Świerblewski,
Konrad
Kosmatka)
Rozdział 2 Constructing Prolog
Programs
z książki Prolog Programming in
Depth autorstwa Michael A.
Covington, Donald Nute, André
Vellino
Wstęp
Prolog interpretuje klauzule jako
definicje procedur. Wynika z tego, że
język
posiada
semantyki
deklaratywne
i
proceduralne.
Jakakolwiek wiedza w Prologu może
być rozumiana deklaratywnie jako
reprezentowanie
wiedzy,
lub
proceduralnie jako pewne określone
akcje obliczeniowe.
Wstęp
Ale nawet dla reprezentacji wiedzy,
Prolog nie jest idealnie deklaratywny;
programista
musi
pewne
kwestie
proceduralne
przechowywać
w głowie. Na przykład, niektóre poprawnie
deklaratywnie
bazy
wiedzy
tworzą
nieskończone pętle. W innych przypadkach,
dwie deklaratywnie równoważne bazy
wiedzy mogą być całkowicie odmienne w
kwestii efektywności obliczeniowej.
Wstęp
W tym rozdziale skupimy się na
proceduralnej interpretacji w Prologu.
Poznamy wbudowany predykaty dla
wejścia/wyjścia
w celu modyfikowania bazy wiedzy
i
kontrolowania
procesu
wstecznego
(backtracking).
Programy w tym rozdziale będą
zawierały bazę wiedzy jak i również
zestawy procedur. Będziemy zazwyczaj
używać prostej bazy wiedzy.
OUTPUT: polecenia write, nl,
display
Wbudowany
predykat
write
traktuje każde termin Prologa jako
własny
argument
i wyświetla go na ekranie. Predykat nl,
który
nie
posiada
argumentów,
przechodzi do nowej linii.
Przykłady write, nl
?- write('Hello'), write('world').
Helloworld
true
?- write('Hello'), nl, write('world').
Hello
world
true
Wielokrotne write
Możemy używać wielokrotnie write w
celu wypisania wartości przechowywanej
przez zmienną, na przykład:
?matka(X,krystyna),
krystyny
jest '), write(X).
Matką krystyny jest barbara.
true
write('Matką
Właściwości write
Jeśli
argument
jest
niezainicjowaną
zmienną,
write
wyświetli
unikalny
symbol
identyfikujący tę zmienną, np. _0001.
?- write(X).
writeq
Zauważmy, że write wyświetla napisy
bez cudzysłowów. Jeśli chcemy, aby write
wypisało ‘Hello world’, wypisze Hello world,
czyli
w postaci dwóch jednostek, a nie jednej, co
jest trudne w późniejszym ewentualnym
wykorzystaniu przez składnię Prologa. Aby
otrzymać napis razem z cudzysłowami,
należy użyć predykatu writeq.
Przykład writeq
?- writeq('hello there').
'hello there'
true
display
Inny predykat, display wyświetla
funktory
z przodu ich argumentów, nawet jeśli
były napisane w innych pozycjach. To
sprawia, że display jest użyteczne dla
poznania wewnętrznej reprezentacji
danych w Prologu.
Przykład display
?- display(2+2).
+(2,2)
true
Jak widzimy, 2+2 nie przedstawia
4, tylko strukturę danych złożonych z
2, + i 2.
write_canonical
Kolejny
write_canonical,
jest
writeq oraz display.
predykat,
kombinacją
?- write_canonical(2+3).
+(2,3)
?- write_canonical('hello there').
'hello there'
Obliczanie i wydruk
Ważne jest odróżnianie zapytań, które
używają
operacji
wejścia/wyjścia,
od
zapytań, które ich nie używają. Na przykład:
?- matka(X,karolina), write(X).
Powyższe zapytanie mówi komputerowi,
żeby znalazł, kto jest matką Karoliny i
wypisał wynik.
Obliczanie i wydruk
Dla kontrastu weźmy poniższe zapytanie:
?- matka(X,karolina).
To zapytanie z kolei mówi komputerowi, żeby
zidentyfikował matkę Karoliny, ale z kolei nic
nie mówi o wydruku. Jeśli wpiszemy kolejne
zapytanie, żeby Prolog wypisał wynik,
zostanie wypisana zmienna X, ponieważ
Prolog zawsze wypisuje wartości zmiennych
zainicjowanych przez zapytania, które nie
użyły operacji wyjścia.
Obliczanie i wydruk
Popularnym błędem jest konstruowanie
predykatu, który ma coś wypisać, kiedy
chcemy, żeby coś obliczył i na odwrót. W
normalnych sytuacjach, dowolny predykat,
który
wykonuje
obliczenia,
powinien
dostarczyć wynik za pomocą zainicjowanego
argumentu, a nie za pomocą wypisania
bezpośrednio
na
ekran.
W ten sposób, wynik może być wykorzystany
później w tym samym programie.
Wymuszanie wracania się z
fail
Wbudowany predykat fail można
wykorzystać do wymuszenia innych
predykatów do wracania się przez
wszystkie rozwiązania.
Wymuszanie wracania się z
fail
Dla przykładu, rozważmy małą bazę wiedzy
Stolice.
?- stolica(kraj,miasto), write(miasto),
write(‘ jest stolicą ‘), write(kraj),nl.
Powyższe zapytanie wyświetli informacje
o pierwszym kraju, które znajdzie, ponieważ
Prolog zakłada, że jeśli użyliśmy write, musi
coś wypisać, niezależnie, czy chcieliśmy to
widzieć.
Wymuszanie wracania się z
fail
W tym miejscu fail odgrywa swoją
rolę.
Aby
wydrukować
wszystkie
alternatywy,
możemy
zbudować
zapytanie w poniższy sposób:
?- stolica(kraj,miasto), write(miasto),
write(‘
jest
stolicą
kraju
‘),write(kraj),nl,fail.
Wymuszanie wracania się z
fail
W miejscu predykatu fail możemy
użyć dowolnego predykatu, który
zwraca
false,
ponieważ
dowolna
porażka powoduje, że Prolog cofa się
do
ostatniej
niewykorzystanej
możliwości.
Wymuszanie wracania się z
fail
Jak to po kolei działa, obrazują kroki poniżej:
?- stolica(kraj,miasto), write(miasto),
write(‘ jest stolicą kraju ‘),write(kraj),nl,fail.
1.Rozwiąż pierwszy cel, stolica(Kraj,Miasto) przez
inicjalizację Kraj jako polska i Miasto jako warszawa.
2.Rozwiąż drugi, trzeci, czwarty i piąty cel (trzy razy
write oraz nl) wypisując Warszawa jest stolicą kraju
Polska i przejście do następnej linii.
3.Rozwiąż ostatni cel, fail. Ten cel nie może być
rozwiązany, więc wróć.
4.Ostatni cel, który ma alternatywy, jest pierwszy, więc
wybierz inny kraj oraz miasto i spróbuj ponownie.
Wymuszanie wracania się z
fail
Poniższe drzewo przedstawia ten proces.
Widać wyraźnie, że na napotkaniu porażki, Prolog wraca na samą
górę do polecenia stolica(Kraj,Miasto), żeby zdobyć alternatywę.

Podobne dokumenty