koniec

Transkrypt

koniec
Języki i paradygmaty programowania
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Wykład 7
Łódź, 22 maja 2010 r.
1/18
Języki i paradygmaty programowania
Wykład 7
Prolog - ”prawie” jak język naturalny
Prolog powstał na początku lat siedemdziesiątych XX wieku, jako odpowiedź na problem
automatycznego dowodzenia twierdzeo.
Powstanie Prologu wiązało się także ze szczególnym rozwojem w tym okresie metod
badania języków naturalnych - wydawało się, że Prolog będzie doskonałą odpowiedzią na te
badania.
Przypomnijmy w tym miejscu o znanym podziale języków programowania ze względu na
stopieo zaawansowania. I tak:
języki pierwszej generacji: języki maszynowe (kod binarny),
języki drugiej generacji: języki symboliczne (asemblery), np. Asembler,
języki trzeciej generacji: języki wysokiego poziomu, proceduralne (imperatywne), np. C++,
języki czwartej generacji: języki bardzo wysokiego poziomu, deklaratywne, np. SQL,
języki piątej generacji: języki sztucznej inteligencji, języki systemów ekspertowych,
najbardziej zbliżone do języka naturalnego, np. Prolog.
Prolog nie stał się językiem programowania o możliwościach języka naturalnego, jednak jego
wkład w informatykę, a szczególnie w zagadnienia sztucznej inteligencji są duże i warto go w
pewnym chociaż minimalnym stopniu poznad.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
2/18
Języki i paradygmaty programowania
Wykład 7
Program w języku Prolog
Oto jeden z prostych przykładów „programów” w Prologu:
lubi(jan, tatry).
lubi(jan, beskidy).
lubi(jerzy, beskidy).
lubi(jerzy, bieszczady).
lubiToSamo(X, Y) :- lubi(X, S), lubi(Y, S), X \= Y.
Program ten (jak każdy w języku Prolog) składa się z faktów:
lubi(jan, tatry).
lubi(jan, beskidy).
lubi(jerzy, beskidy).
lubi(jerzy, bieszczady).
oraz reguł:
lubiToSamo(X, Y) :- lubi(X, S), lubi(Y, S), X \= Y.
Ten program jest zupełnie ”samowystarczalny” - nie potrzebujemy nigdzie dodatkowo
deklarowad, co to znaczy lubi bądź lubiToSamo. Wszystko, co potrzeba do wykorzystania
tego programu, już tu jest.
Samo uruchomienie polega teraz na wpisaniu celu i przejrzeniu wszystkich odpowiedzi
udzielonych przez Prolog.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
3/18
Języki i paradygmaty programowania
Wykład 7
Program w języku Prolog
Oto kilka przykładów zapytao (do programu z poprzedniego slajdu), wraz z odpowiedziami
języka. Znaki ?- są wypisywane przez interpreter:
?- lubi(jan, beskidy).
true
?- lubi(jan, sudety).
false
?- lubi(jan, X).
X = tatry;
X = beskidy;
false
?- lubi(X, beskidy)
X = jan;
X = jerzy;
false
?- lubi(filip, tatry).
false
?- lubi(filip, X).
false
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
4/18
Języki i paradygmaty programowania
Wykład 7
Program w języku Prolog
Cel może byd:
• konkretny (fakt),
•może zawierad zmienne (reguła).
W pierwszym przypadku interpreter odpowiada true lub false, w zależności od tego, czy
udało mu się znaleźd potwierdzenie wpisanego celu.
W drugim przypadku interpreter znajduje wszystkie możliwości spełnienia wpisanej relacji
(po czym odpowiada false - co oznacza, że nie ma już więcej rozwiązao). Zauważmy, że
odpowiedź przecząca oznacza, że interpreter nic nie wie na żądany temat - a nie że potrafi
udowodnid fałszywośd wpisanego celu.
Innymi słowy, Prolog działa przy założeniu, że mamy ”zamknięty świat faktów”, o którym
wiemy wszystko; to, czego nie wiemy, nie istnieje...
Zauważmy, że:
• Możemy pytad również o byty, o których wcześniej nie wspomnieliśmy ani słowem. Tak jest
np. w pytaniu
lubi(filip, tatry).
Wbrew pozorom, nie zawsze uzyskamy wtedy odpowiedź false. Możemy otrzymad
odpowiedź twierdzącą, jeśli wynika to z mniej szczegółowych stwierdzeo programu.
• Nazwy zmiennych we wpisanym celu nie mają nic wspólnego z ewentualnymi nazwami
zmiennych w programie.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
5/18
Języki i paradygmaty programowania
Wykład 7
Program w języku Prolog
Powyższe przykłady celów i odpowiedzi pokazują, że można zapytad o dowolny fragment
relacji, a interpreter spróbuje dopasowad (ściślej mówimy uzgodnid lub zunifikowad;
dopasowanie to właściwie techniczny sposób dokonania uzgodnienia) wartości zmiennych
tak, by uzyskad stwierdzenia zgodne z posiadanym stanem wiedzy (czyli stwierdzeniami w
programie). Wszystkie powyższe przykłady były jednak ograniczone do pytao, które dało się
rozstrzygnąd przez pojedyncze dopasowanie celu do stwierdzeo w programie. Prolog jest
oczywiście znacznie bardziej zręczny i potrafi udowodnid stwierdzenia, które wymagają
uzgodnieo w wielu etapach.
Np:
?- lubiToSamo(jan, jerzy).
true
?- lubiToSamo(X, Y).
X = jan, Y = jerzy;
X = jerzy, Y = jan;
No
Zauważmy, że stwierdzenia w których występują zmienne:
lubiToSamo(X, Y) :- lubi(X, S), lubi(Y, S), X \= Y.
traktujemy tak jakby stał przed nimi kwantyfikator uniwersalny wiążący wszystkie owe
zmienne. Dzięki temu stwierdzenie to staje się regułą na podstawie której interpreter może
wnioskowad o ”osobach lubiących to samo”.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
6/18
Języki i paradygmaty programowania
Wykład 7
Jak rozumied klauzule?
Klauzula złożona z pojedynczej struktury prologowej, to stwierdzenie, które przyjmujemy za
fakt, np.
lubi(jan, tatry).
Występujące w tej klauzuli atomy: lubi, jan i tatry - nie mają tu żadnego innego znaczenia niż
powiązanie ich w taką właśnie klauzulę, która następnie może byd wykorzystana przy
poszukiwaniu odpowiedzi przez interpreter. Innymi słowy, atomy oznaczają po prostu siebie i
dopóki nie użyjemy ich w jakimś konkretnym kontekście (np. w operacji arytmetycznej), nie
wymagamy od nich żadnych własności. Oczywiście intuicyjne rozumienie takiej klauzuli-faktu
to stwierdzenie:
Jan lubi Tatry
czyli że podane w nawiasach obiekty spełniają relację podaną na początku. A zatem funktor
lubi spełnia rolę nazwy relacji, zaś atomy (w tym przypadku parametry): jan, tatry - rolę
elementów tę relację spełniających. Zamiast atomów mogą również pojawiad się stałe
liczbowe lub napisowe oraz całe struktury.
Drugi typ klauzul to klauzule postaci:
B :- A1, A2,..., Am
takie jak podana chwilę wcześniej reguła ”lubid to samo”. Klauzule tego rodzaju prawie
zawsze zawierają zmienne. W praktyce klauzulę rozumiemy jako definicję nowej relacji - nie
poprzez wyliczenie obiektów ją spełniających, lecz poprzez określenie reguły wiążącej ją z
innymi relacjami. W trakcie poszukiwania odpowiedzi interpreter może wykorzystad taką
klauzulę, uzgadniając odpowiednio zmienne.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
7/18
Języki i paradygmaty programowania
Wykład 7
Rola struktur
Struktura to twór postaci: funktor(listaParametrów)
gdzie parametry są atomami, zmiennymi lub innymi strukturami, rozdzielonymi przecinkami.
Term to stała, zmienna lub struktura.
Stała może byd atomem (składnia - jak typowy identyfikator zaczynający się od małej litery lub napis
ujęty w apostrofy) lub liczbą. System typów Prologu jest niezbyt rozbudowany i zazwyczaj obejmuje
liczby całkowite, zmiennopozycyjne oraz napisy, przy czym napisy w podwójnych cudzysłowach
utożsamiane są z listą kodów znaków, zaś napisy w apostrofach - z atomami.
Zmienne zaczynają się z dużej litery.
Struktury mogą występowad zarówno w roli danych, jak i w roli zbliżonej do funkcji w klasycznych
językach programowania.
W rozważanym dotychczas przykładzie struktury z funktorem lubi uznalibyśmy zapewne za dane,
natomiast strukturę z funktorem lubiToSamo za coś w rodzaju funkcji. Podział ten jest jednak sztuczny i
bierze się po prostu z naszych przyzwyczajeo. Prolog traktuje wszystkie struktury tak samo,
wykorzystując je w uzgodnieniach. Zauważmy, że do naszego programu moglibyśmy dodad klauzulę:
lubi(_, pieniny).
Można ją interpretowad jako stwierdzenie: ”każdy lubi pieniny. W tej sytuacji funktor lubi przestaje
oznaczad tylko dane. Zauważmy, że taka klauzula pozwala interpreterowi odpowiedzied twierdząco np.
na poniższe pytania:
lubi(X, pieniny).
lubi(filip, pieniny).
lubi(filip, _).
lubi(filip, X).
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
8/18
Języki i paradygmaty programowania
Wykład 7
Rola struktur
Warto zauważyd, że jeśli jakaś zmienna występuje w klauzuli tylko raz, to należy ją zapisad
jako zmienną anonimową, czyli za pomocą znaku podkreślenia: _. Taka sytuacja oznacza,
że wartośd tej zmiennej nie będzie potrzebna w żadnym innym miejscu.
W szczególności dwa wystąpienia znaku podkreślenia oznaczają dwie zupełnie nie
związane ze sobą zmienne anonimowe. Tak więc np. klauzula:
zna(X, X).
oznacza ”każdy zna samego siebie”, natomiast klauzula:
zna(_, _).
oznacza ”każdy zna każdego”. Zmienna anonimowa użyta we wpisanym celu oznacza, że
nie chcemy znad wartości, jakie interpreter nada tej zmiennej, próbując osiągnąd cel.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
9/18
Języki i paradygmaty programowania
Wykład 7
Rola struktur
Przykład struktur z funktorem lubi kojarzyd się byd może nie tyle z reprezentacją ”obiektów pierwotnych”
bazy danych (czyli, powiedzmy, rekordów w tabeli w relacyjnej bazie danych), co raczej z reprezentacją
zależności między takimi obiektami. Popatrzmy więc na taki przykład:
pracownik(imię(jan),
nazwisko(kowalski),
adres(ulica(długa),nr(2),miasto(kraków)),
telefon(’0123456789’)).
Użyliśmy tu zagnieżdżonych struktur do reprezentacji danych pracowników. W potocznym rozumieniu
owi pracownicy są ”obiektami pierwotnymi”. Zauważmy jednak, że w Prologu sposób reprezentowania
jest w obydwu przypadkach w istocie taki sam.
Reprezentacja taka jak powyżej daje nam możliwości podobne do rekordów przy znacznie większej
elastyczności. Przyjrzyjmy się ponownie pracownikom:
• Funktor pracownik użyty jest w roli podobnej do nazwy typu.
• Funktory imię, nazwisko itp. spełniają rolę analogiczną do pól rekordu.
• Atomy i liczby zachowują się jak wartości pól.
Mamy tu obiekty (pracowników) opisane w sposób samoistny - bez odwoływania się do zewnętrznych
definicji typów. Mechanizm ten, chociaż nie pozwala np. na statyczne sprawdzenie zgodności typu, ma
cechy przyzwoitego typowania. Otóż wszelkie wykorzystanie takich obiektów musi następowad przez
uzgodnienie, a żeby ono się powiodło, konieczna jest pełna zgodnośd struktur (nazwy, ilości argumentów
i podstruktury). Dodajmy, że atomy można traktowad jako funktory zeroargumentowe.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
10/18
Języki i paradygmaty programowania
Wykład 7
Zmienne i ich ukonkretnianie
Zmienne w Prologu są zupełnie odmienne od zmiennych w językach imperatywnych i tylko
trochę podobne do zmiennych w językach funkcyjnych. Owo podobieostwo polega na tym,
że zmienna prologowa nie może dowolnie zmieniad wartości tak, jak się to dzieje przy
podstawieniach - tych zresztą w ogóle w Prologu nie ma. W Prologu nadawanie wartości
zmiennym następuje w wyniku uzgodnieo - powiemy o nich dokładniej w dalszej części
wykładu.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
11/18
Języki i paradygmaty programowania
Wykład 7
Ukonkretnianie zmiennych
Zmienna w programie Prologowym reprezentuje zupełnie nieokreślony byt, bez typu. W trakcie obliczeo,
w rezultacie uzgodnieo następuje ukonkretnianie zmiennej, czyli bliższe określenie bytu
reprezentowanego przez zmienną. Ów byt będziemy nazywali konkretyzacją zmiennej.
Ukonkretnienie może byd:
• całkowite,
• częściowe.
W przypadku ukonkretniania całkowitego zmienna utożsamia się z termem niezawierającym zmiennych i
nie podlega dalszemu ukonkretnianiu. W tym momencie można ją postrzegad jak zainstancjonowaną
zmienną w programie funkcyjnym.
W przypadku ukonkretniania częściowego zmienna reprezentuje term, który wciąż zawiera inne
zmienne, i może byd ukonkretniana dalej.
Ciekawym przypadkiem jest ukonkretnienie, które następuje przy uzgadnianiu dwóch dotychczas
nieukonkretnionych zmiennych. Nie pojawia się wtedy żaden bardziej szczegółowy opis struktury
reprezentowanej przez zmienną, gdyż obydwie zmienne na razie reprezentują byty nieokreślone.
Dwie zmienne zostają natomiast utożsamione, czyli odtąd każde wystąpienie i ukonkretnienie
jednej z nich odnosi się tak samo do drugiej.
Ukonkretnienie zmiennej nie może zostad zmienione na inne, może natomiast zostad anulowane
w wyniku nawrotu. Generalnie odnosi się to do ostatniego etapu ukonkretnienia - zmienna wraca
do poprzedniej konkretyzacji, a nie do stanu całkowicie nie ukonkretnionego.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
12/18
Języki i paradygmaty programowania
Wykład 7
Przykłady ukonkretniania
Przykład 1
Do programu:
lubi(jan, tatry).
lubi(jan, beskidy).
lubi(jerzy, beskidy).
lubi(jerzy, bieszczady).
lubiToSamo(X, Y) :- lubi(X, S), lubi(Y, S), X \= Y.
zadajemy zapytanie:
lubiToSamo(jan,X).
W pierwszym etapie następuje dopasowanie owego celu do definicji
lubiToSamo(X, Y)
co skutkuje dwoma uzgodnieniami:
•Atom jan zostaje dopasowany do zmiennej X z definicji. W rezultacie zmienna X zostaje
ukonkretniona do wartości jan.
•Zmienna X z celu zostaje uzgodniona ze zmienną Y z definicji. W rezultacie powstaje jedna
zmienna.
Oczywiście zmienna X, której konkretyzacją jest atom jan, nie ma nic wspólnego z tą drugą.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
13/18
Języki i paradygmaty programowania
Wykład 7
Przykłady ukonkretniania
Przykład 2
Do programu:
pracownik(imię(jan),
nazwisko(kowalski),
adres(ulica(długa),nr(2),miasto(kraków)),
telefon(’0123456789’)).
zadajemy zapytanie:
pracownik(X, Y, Z, telefon(’0123456789’)).
Cel pasuje do definicji jednego, konkretnego pracownika, a zatem mamy trzy uzgodnienia z
następującymi skutkami:
• Zmienna X zostaje ukonkretniona do imię(jan).
• Zmienna Y zostaje ukonkretniona do nazwisko(kowalski).
• Zmienna Z zostaje ukonkretniona do adres(ulica(długa), nr(2), miasto(kraków)).
Zauważmy, że wartościami zmiennych stają się tu całe struktury, a nie pojedyncze atomy.
Druga obserwacja to to, że interpretera Prologu można użyd wprost jako mechanizmu
wyszukiwania w bazie danych - podajemy znane elementy (tu: telefon), a interpreter
znajduje wszystkie pasujące ”rekordy”.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
14/18
Języki i paradygmaty programowania
Wykład 7
Przykłady ukonkretniania
Przykład 3
Do programu:
pracownik(imię(jan),
nazwisko(kowalski),
adres(ulica(długa),nr(2),miasto(kraków)),
telefon(’0123456789’)).
pracownik(imię(stefan),
nazwisko(nowak),
adres(ulica(jodlowa),nr(2),miasto(warszawa)),
telefon(’0123499999’)).
zadajemy zapytanie:
pracownik(imię(X), nazwisko(Y), adres(A1, A2, A3), telefon(Z)).
Tym razem cel pasuje do obydwu pracowników, więc mamy jeden zestaw ukonkretnieo,
nawrót (a więc anulowanie ukonkretnieo) i drugi zestaw. Konkretyzacje zmiennych X, Y, A1,
A2, A3 i Z w poszczególnych zestawach to oczywiście dane dwóch pracowników:
X = jan, Y = kowalski, A1 = ulica(długa), A2 = nr(2), A3 =
miasto(kraków), Z = ’0123456789’
oraz
X = jerzy, Y = nowak, A1 = ulica(krótka), A2 = nr(123), A3 =
miasto(kraków), Z = ’0987654321’.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
15/18
Języki i paradygmaty programowania
Wykład 7
Przykłady ukonkretniania
W ostatnim przykładzie w przypadku zmiennych X, Y i Z dotarliśmy tu już do atomów,
natomiast w przypadku A1, A2 i A3 otrzymujemy struktury, gdyż na tym poziomie
zagnieżdżenia odbyło się uzgodnienie.
Dwa ostatnie przykłady pokazują, że uzgodnienia mogą byd na różnych poziomach
zagnieżdżenia. Pozwala to zadawad pytania o różnym stopniu szczegółowości. Trzeba
natomiast pamiętad, że zawsze należy przestrzegad arności (argumentowości) funktora. A
zatem niepoprawne, właśnie ze względu na niewłaściwą arnośd, są cele:
pracownik(imię(X), nazwisko(Y), adres(A), telefon(Z)).
pracownik(imię(X), nazwisko(Y), adres(A1, A2), telefon(Z)).
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
16/18
Języki i paradygmaty programowania
Wykład 7
Przykłady ukonkretniania zmiennych
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
17/18
Języki i paradygmaty programowania
Wykład 7
KONIEC
Dziękuję za uwagę 
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
Łódź, 22 maja 2010 r.
18/18