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