Both sides previous revision
Poprzednia wersja
Nowa wersja
|
Poprzednia wersja
|
pl:prolog:prolog_lab:prolog_lab_6 [2007/11/28 12:56] wojnicki |
— (aktualna) |
====== 6 LAB: Metaprogramowanie w Prologu ====== | |
| |
| |
===== WPROWADZENIE ===== | |
| |
| |
==== Temat: Sprawdzanie typów termów ==== | |
| |
| |
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: | |
| |
<code prolog> | |
var(X) | |
nonvar(X) | |
</code> | |
| |
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ą | |
| |
==== Temat: Konstruowanie i dekompzycja termów ==== | |
| |
| |
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 | |
| |
==== Temat: Definiowanie operatorów ==== | |
| |
| |
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. | |
| |
Zdefiniowane w standardzie ISO operatory to: | |
| |
<code> | |
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 ^ | |
</code> | |
| |
Wszystkie mogą być zredefiniowane!. | |
| |
==== Temat: Konstruowanie klauzul i Metainterpretery ==== | |
| |
| |
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. | |
| |
==== Temat: Przykłady systemów regułowych ==== | |
| |
| |
* System: CAR | |
| |
Źródło: Michael A. Covington, Donald Nute and André Vellino, Prolog programming in depth, Prentice-Hall, 1996. | |
| |
Cechy: | |
o klauzule Prologu jako reprezentacja wiedzy | |
o wbudowany mechanizm Prologu | |
o wnioskowanie wstecz | |
o trywialny :) | |
| |
System: pl/car.pro | |
| |
* System: OOPS | |
| |
Źródło: Dennis Merritt, Building Expert Systems in Prolog Springer-Verlag, 1989. | |
| |
Cechy: | |
o własna reprezentacja reguł | |
o kodowanie reguł na termach Prologu | |
o własny mechanizm wnioskujący | |
o wnioskowanie wprzód | |
o wymienne bazy wiedzy | |
| |
Mechanizm wnioskujący: pl/oops.pro | |
| |
Baza wiedzy: pl/animal_kb.pro | |
| |
* | |
| |
System: XSHELL | |
| |
Źródło: Michael A. Covington, Donald Nute and André Vellino, Prolog programming in depth, Prentice-Hall, 1996. | |
| |
Cechy: | |
o klauzule Prologu jako reprezentacja wiedzy | |
o rozbudowana reprezentacja reguł | |
o wbudowany mechanizm Prologu | |
o wnioskowanie wstecz | |
o wymienne bazy wiedzy | |
o rozbudowane przetwarzanie | |
| |
Mechanizm wnioskujący: pl/xshell.pro | |
| |
Baza wiedzy: pl/cichlid.pro | |
| |
===== ĆWICZENIA ===== | |
| |
| |
==== 6.1 Ćwiczenie: Sprawdzanie typów termów ==== | |
| |
| |
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). | |
| |
?- number(3). | |
?- integer(3). | |
?- integer(3.14). | |
?- float(3.14). | |
?- float(3). | |
| |
?- compound(ala). | |
?- compound(ala(ma,kota)). | |
?- compound(3). | |
| |
==== 6.2 Ćwiczenie: Konstruowanie i dekompzycja termów ==== | |
| |
| |
Proszę przećwiczyć przetwarzanie termów: | |
| |
?- A =.. [ala, ma, kota]. | |
?- 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). | |
| |
==== 6.3 Ćwiczenie: Definiowanie operatorów ==== | |
| |
| |
Proszę wpisać do pliku oper1.pro | |
| |
:- 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. | |
| |
Przetestować: | |
| |
?- ma(X,Y). | |
| |
?- display(jas ma kota i psa). | |
| |
?- display(ala ma jasia i angine i dosc_agh). | |
| |
==== 6.4 Ćwiczenie: Konstruowanie klauzul i Metainterpretery ==== | |
| |
| |
Proszę wczytać program pl/rodzina1.pro. | |
| |
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.pro 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: pl/readstr.pro | |
| |
a następnie przetestować i przemyśleć: | |
| |
?- odpowiedz. | |
'matka' czy 'ojciec'? ojciec | |
kogo? robert | |
| |
Dopisać do pliku meta.pro 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 pl/tracerdepth.pro | |
| |
Przetestować: | |
| |
?- traced(matka(kasia,Y)). | |
| |
==== 6.5 Ćwiczenie: Przykłady systemów regułowych ==== | |
| |
| |
Przetestować systemy: | |
| |
* System: CAR | |
| |
System: pl/car.pro | |
| |
Plik pomocniczy: pl/getyesno.pro | |
| |
* System: OOPS | |
| |
Mechanizm wnioskujący: pl/oops.proBaza wiedzy: pl/animal_kb.pro | |
| |
* | |
| |
System: XSHELL | |
| |
Mechanizm wnioskujący: pl/xshell.pro | |
| |
Pliki pomocnicze: pl/readstr.pro , pl/readnum.pro , pl/writeln.pro , pl/getyesno.pro | |
| |
Baza wiedzy: pl/cichlid.pro | |
| |
Analizując ich pracę i sposób implementacji, proszę zwrócić uwagę na: | |
| |
* sposób reprezentacji reguł, jak są zapisywane reguły w bazie wiedzy systemu, z jakich operatorów korzystają, | |
* sposób implementacji mechanizmy wnioskującego, na jakich rozwiązaniach się opiera. | |
| |
| |
| |
| |
<code prolog> | |
a(1). | |
a(2). | |
b(4). | |
b(3). | |
| |
wyp1(F,X):- | |
F, | |
F =.. [_,X]. | |
| |
%wyp1(a(_),X). | |
%wyp1(b(_),X). | |
| |
wyp(F,X):- | |
functor(Pred,F,1), | |
Pred, | |
Pred =.. [_,X]. | |
| |
%wyp(a,X). | |
%wyp(b,X). | |
</code> | |
| |