Prolog dostarcza szeregu predykatów, pozwalających na analizowanie typów termów.
Po pierwsze można stwierdzić, czy term jest niewiadomą (zmienną logiczną) o nieustalonej wartości, czy też ma określoną wartość, czyli jest stałą, lub zmienną o wcześniej ustalonej wartości (po pomyślnej unifikacji).
Służą do tego predykaty:
var(X). nonvar(X).
Poza tym, jest szereg predykatów sprawdzających, czy term jest:
atom
atomem logicznym (stałą, napisem)
atomic
liczbą lub atomem
number
liczbą
compound
złożoną strukturą
integer
liczbą całkowitą
float
liczbą zmiennoprzecinkową
Ćwiczenie:
Proszę przetestować poniższe:
?- var(X). ?- var(X),X=2. ?- X=2,var(X). ?- atom(X). ?- atom(3). ?- atom(a). ?- atom(+). ?- atom(:=). ?- atom('ala'). ?- atomic(a). ?- atomic(3). ?- atomic(+). ?- atomic(X). ?- number(ala). ?- number(3). ?- integer(3). ?- integer(3.14). ?- float(3). ?- float(3.14). ?- compound(ala). ?- compound(ala(ma,kota)). ?- compound(3).
Uwaga: compound
nie nadaje się do „wykrywania” list, bo:
?- compound([]).
Z racji tego, iż termy sa podstawową metodą strukturalizacji danych w Prolog, istnieje kilka mechanizmów wspomagających ich przetwarzanie:
=..
operator pozwala na dynamiczną zamianę termu na listę i vice versa
functor(T,N,A)
predykat jest prawdziwy, jeżeli N pokrywa się z nazwą termu T o arności A
arg(N,T,A)
predykat jest prawdziwy, jeżeli A jest Ntym argumentem termu T
Ćwiczenie:
Proszę przećwiczyć przetwarzanie termów:
?- A =.. [ala, ma, asa]. ?- ala(ma,kota,w(ciapki(rozowe))) =.. A.
Przeanalizować:
?- functor(ala(ma,kota),F,A). ?- CzyTo = ala, OLiczbie = 2, functor(ala(ma,kota),CzyTo,OLiczbie). ?- CzyTo = kasia, OLiczbie = 2, functor(ala(ma,kota),CzyTo,OLiczbie). ?- functor(ala(ma,kota),F,_), write('To jest funktor \''), write(F), write('\'.'). ?- arg(X,ala_ma(kota,psa,schiza),A). ?- arg(2,ala_ma(kota,psa,schiza),A). ?- functor(A,riverside,3). ?- functor(A,riverside,4), arg(1,A,voices), arg(4,A,head).
Poniższy kod (predykaty wyp0/2
, wyp1/2
, wyp2/2
, wyp3/2
) prezentuje sposoby odwoływania się do predykatów przekazywanych jako argumenty.
Przykłady użycia znajdują się w części dalszej.
a(1). a(2). b(4). b(3). wyp0(F,_) :- call(F). wyp1(F,X) :- F, F =.. [_,X]. wyp2(F,X) :- functor(Pred,F,1), Pred, Pred =.. [_,X]. wyp3(F/A,X) :- A = 1, functor(Pred,F,A), Pred, Pred =.. [_,X].
Wykonaj zapytania będące przykładami użycia powyższych predykatów:
?- wyp0(a(X),X). ?- wyp0(b(X),X). ?- wyp1(a(_),X). ?- wyp1(b(_),X). ?- wyp2(a,X). ?- wyp2(b,X). ?- wyp3(a/1,X). ?- wyp3(b/1,X).
W prologu bardzo łatwo można definiować własne operatory, co ułatwia przetwarzanie danych.
Realizowane jest to przez predykat :- op(P, T, N), który definiuje N, jako operator typu T, o priorytecie P. Zobacz:
Zdefiniowane w standardzie ISO operatory to:
1200 xfx -->, :- 1200 fx :-, ?- 1150 fx dynamic, discontiguous, initialization, module_transparent, multifile, thread_local, volatile 1100 xfy ;, | 1050 xfy ->, op*-> 1000 xfy , 954 xfy \ 900 fy \+ 900 fx ~ 700 xfx <, =, =.., =@=, =:=, =<, ==, =\=, >, >=, @<, @=<, @>, @>=, \=, \==, is 600 xfy : 500 yfx +, -, /\, \/, xor 500 fx +, -, ?, \ 400 yfx *, /, //, rdiv, <<, >>, mod, rem 200 xfx ** 200 xfy ^
Wszystkie mogą być zredefiniowane!.
Gdyby nie operatory, to prosty program w Prologu:
go :- write('Hello '), write('World\n'). :- go.
Musialby wyglądać następująco (wszytko w notacji prefiksowej, zapisane jako termy):
:- (go,','(write('Hello '), write('World\n'))). :- (go).
Uwaga: obydwa programy są równoważne. W drugim programie widać, że klauzule złożone również zapisane są jako termy.
Patrz również:
Ćwiczenie:
Proszę wpisać do pliku oper1.pl
:- op(100,xfy, matka). julia matka marcin.
a nastepnie przetestować:
?- X matka Y.
Dopisać do pliku:
:- op(300, xfx, ma). :- op(200, xfy, i). jas ma kota i psa. ala ma jasia i angine i dosc_agh. rybki i kanarki.
Przetestować:
?- ma(X,Y). ?- ma(X,i(A,B)). ?- ma(A,i(B,i(C,D))). ?- Kto ma Co. ?- Kto ma Co i Cosinnego. ?- Kto ma Cos i CosInnego i Jeszcze. ?- display(jas ma kota i psa). ?- display(ala ma jasia i angine i dosc_agh).
Co zwróci poniższe zapytanie?
?- i(A,B).
Podpowiedź: zwróć uwagę na priorytety operatorów.
W Prologu występują dwa silne mechnizmy wspomagające metainterpretację kodu:
call(X)
wywołuje X, jako cel Prologu,
clause(Head,Body)
odszukuje klauzulę o nagłówku Head, gdzie Body jest unifikowane z ciałem klauzuli; w przypadku faktów Body=true.
Meta programowanie to tworzenie programów, które przetwarzają kod innych programów. Przykłady metaprogramowania znaleźć można w np.: kompilatorach, analizatorach kodu, generatorach kodu. W Prologu metaprogramowanie jest naturalną techniką, dzięki czemu pisanie programów działających w diametralnie różnych paradygmatach jest proste.
Ćwiczenie:
Proszę wczytać program rodzina1.pl
Uruchomić:
?- listing(kobieta). ?- call(kobieta(X)). ?- clause(kobieta(X),B). ?- listing(matka). ?- Kto = kasia, call(matka(Kto,Kogo)), write(Kto), write(' jest matka '), write(Kogo). ?- Matka = kasia, Dziecko = robert, clause(matka(Matka,Dziecko),Kiedy), write(Matka), write(' jest matka '), write(Dziecko), write(' wtedy gdy: '), write(Kiedy).
Proszę do pliku meta.pl wpisać predykat:
:- include(readstr). odpowiedz :- write('\'matka\' czy \'ojciec\'? '), read_atom(X), write('kogo? '), read_atom(Y), Q =.. [X,Kto,Y], display(Q), call(Q), write(Kto), nl.
Uwaga: potrzebny jest dodatkowy plik: readstr.pl
a następnie przetestować i przemyśleć:
?- odpowiedz. 'matka' czy 'ojciec'? ojciec kogo? robert
Dopisać do pliku meta.pl następujące proste metainterpretery Prologu:
rozwiaz1(G) :- call(G). rozwiaz2(true) :- !. rozwiaz2((G1,G2)) :- !, rozwiaz2(G1), rozwiaz2(G2). rozwiaz2(G) :- clause(G,B), rozwiaz2(B). rozwiaz3(true) :-!. rozwiaz3((G1,G2)) :- !, rozwiaz3(G1), rozwiaz3(G2). rozwiaz3(G) :- write('Wywoluje: '), write(G), nl, clause(G,B), rozwiaz3(B), write('Wyjscie: '), write(G), nl.
Pierwszy z nich po prostu wywołuje pojedynczy cel, tak jak powłoka SWI.
Drugi pozwala na zadanie celu złożonego z 2 części.
Trzeci działa podobnie, ale śledzi wykonywanie.
Przetestować ich działanie:
?- rozwiaz1(matka(kasia,X)). ?- rozwiaz1((matka(kasia,X), matka(Y,robert))). ?- rozwiaz2((matka(kasia,X), matka(Y,robert))). ?- rozwiaz3((matka(kasia,X), matka(Y,robert))).
Proszę pobrać kod tracerdepth.pl
Przetestować:
?- traced(matka(kasia,Y)).
W Prologu niezwykle prosto tworzy się systemy ekspertowe.
W systemie ekspertowym można wyróżnić następujące elementy:
Rysunek 1: Struktura Systemu Ekspertowego.
Poniżej podane są przykłady różnych systemów.
Źródło: Michael A. Covington, Donald Nute and André Vellino, Prolog programming in depth, Prentice-Hall, 1996.
Cechy:
System: car.pl Dodatkowo korzysta on z pliku getyesno.pl
Przetestować działanie systemu. System diagnozuje przyczyną awarii samochodu.
W przypadku tego systemu elementy systemu ekspertowego są odwzorowane przez:
System: car.pl
Plik pomocniczy: getyesno.pl
Źródło: Dennis Merritt, Building Expert Systems in Prolog, Springer-Verlag, 1989.
Cechy:
Mechanizm wnioskujący: native.pl
Bazy wiedzy: birds_kb.pl
Uruchomienie: załadować native.pl i wywołać main.
Źródło: Dennis Merritt, Building Expert Systems in Prolog, Springer-Verlag, 1989.
Cechy:
Mechanizm wnioskujący: oops.pl
Bazy wiedzy: room_kb.pl animal_kb.pl
Uruchomienie: załadować oops.pl i wywołać main.
Źródło: Michael A. Covington, Donald Nute and André Vellino, Prolog programming in depth, Prentice-Hall, 1996.
Cechy:
Mechanizm wnioskujący: xshell.pl
Baza wiedzy: cichlid.pl
Pliki pomocnicze: readstr.pl , readnum.pl , writeln.pl , getyesno.pl
Należy załadować plik z bazą wiedzy (ten z kolei ładuje mechanizm wnioskujący) i użyć predykatu xshell.
Ćwiczenie:
Przetestuj powyższe systemy.
Analizując ich pracę i sposób implementacji, proszę zwrócić uwagę na:
Zbuduj bazę wiedzy dla własnego systemu regułowego (dla wybranej implementacji). Propozycje dziedzin podane są poniżej.
System rozpoznaje psy. Należy opisać kilka/naście znanych ras psów na podstawie: http://pl.wikipedia.org/wiki/Grupy_FCI, http://atlaspsow.w.interia.pl, http://rasy-psow.com, http://www.psy.elk.pl/rasypsow/. Warto wybrać przedstawicieli z różnych grup FCI.
W celu identyfikacji rasy trzeba wybrać kilka podstawowych cech, w tym płeć (powiązana z rozmiarem!), wagę, rozmiar, umaszczenie, kształt głowy, uszy, etc.
Podobny do w.w. system rozpoznający ptaki występujące w Polsce. Należy oprzeć się na: http://ptaki.luzik.proste.pl, http://ptaki.zwierzeta.ekologia.pl.
Tu studenci mogą wpisywać swoje uwagi…
— Grzegorz J. Nalepa 2009/05/06 09:13