Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Kunikowska Ewelina Grzechowski Ariel

Podobne prezentacje


Prezentacja na temat: "Kunikowska Ewelina Grzechowski Ariel"— Zapis prezentacji:

1 Kunikowska Ewelina Grzechowski Ariel
Zaawansowany prolog Kunikowska Ewelina Grzechowski Ariel

2 Krótkie przypomnienie
Term to: stała, zmienna, struktura. Każdy term zapisywany jest jako ciąg znaków, tworzących cztery kategorie: duże litery: A-Z małe litery: a-z cyfry: 0-9 znaki specjalne

3 Krótkie przypomnienie
Stałą nazywamy konkretne obiekty lub relacje. Istnieją dwa rodzaje stałych: atomy liczby Przykład: jas, malgosia, posiada, je Atomy składają się z: symboli, liter, cyfr znaku podkreślenia (zaczynamy zawsze małą literą), dowolnych znaków, jeśli ujęte są w pojedynczy cudzysłów. Liczby: -17, 23, 99.9, 123e-3

4 Krótkie przypomnienie
Zmienne mają postać atomu złożonego z liter, cyfr lub znaku podkreślenia z zastrzeżeniem, że pierwszym znakiem musi być duża litera. Czasem interesuje nas tylko czy coś jest prawdą, ale zupełnie nie interesuje nas co. Jak sprawdzić, czy ktoś lubi Jasia? W takich sytuacjach możemy użyć zmiennej anonimowej zapisywanej jako jeden znak podkreślenia. lubi(_,jas).

5 Krótkie przypomnienie
Struktura, inaczej term złożony, to obiekt złożony z innych obiektów. Przykład: posiada(‘Ewelina’,’prawo jazdy’).

6 Struktury a drzewa Zwykle łatwiej jest zrozumieć budowę struktury, gdy jest ona zapisana w postaci drzewa. W drzewie tym korzeniem jest funktor, a gałęziami elementy struktury. Ponadto struktury można zagnieżdżać.

7 Struktury a drzewa-przykład 1

8 Struktury a drzewa Drzewa również mogą opisywać zmienne w strukturach, w szczególności ukazując powiązania między nimi. Przykład:

9 Listy Lista to bardzo popularna struktura danych. Definiuje się ją jako ciąg uporządkowanych(tzn. kolejność ma znaczenie) elementów dowolnej długości. Elementy mogą być dowolnymi termami: stałymi zmiennymi innymi strukturami

10 Listy w Prologu Lista w Prologu to szczególny przypadek struktury, którą można zapisać w formie specjalnego rodzaju drzewa. Listę pustą oznaczamy poprzez [ ], a operatorem składania list jest . Ogólnie lista w Prologu dzieli się na dwie części : pierwszy element zwany głową oraz „resztę” zwaną ogonem

11 Listy w Prologu – przykłady
[a, b, c] w zapisie formalnym .(a, .(b, .(c , []))) [[1,2],[3]] w zapisie formalnym .(.(1, .(2, [])), .(.(3, []), []))

12 Listy w Prologu – c.d. Wróćmy do kwestii głowy i ogona. W zapisie formalnym wygląda to następująco: .( głowa, ogon) . Zapis ten ułatwia operator | , więc wygląda to tak: [ głowa|ogon] W takim razie przykłady z poprzedniego slajdu można zapisać następująco: [a|b|c] [[1|2]|[3]]

13 polaczListy( G, O, [ G| O]).
Listy w Prologu – c.d. Zapis ten uwidacznia się nie tyle dla konkretnych list, co dla dopasowań. Rozważmy przykładową klauzulę: polaczListy( G, O, [ G| O]). Klauzula ta umożliwia połączenie list G i O (polaczListy(1,[2,3],X) da wynik X=[1,2,3]) rozdzielenie gotowej listy na dwie pomniejsze (polaczListy(X,Y,[1,2,3]) da wynik X=1,Y=[2,3])

14 Przeszukiwanie rekurencyjne
Często konieczne jest przeszukiwanie struktur w Prologu celem znalezienia pewnych informacji. Kiedy struktury mogą mieć inne struktury jako argumenty, konieczne jest przeszukiwanie rekurencyjne

15 Przeszukiwanie rekurencyjne
Aby zrozumieć to zagadnienie, posłużymy się przykładem. Napiszmy ‘funkcję’, która sprawdzi przynależność elementu do listy. Najpierw sprawdźmy, czy poszukiwany element jest w ‘głowie’ naszej listy.

16 Przeszukiwanie rekurencyjne
Zatem taka klauzula wygląda następująco nalezy( X, [X|_]). Jednak co w przypadku, gdy nasz element nie znajduje się w ‘głowie’?

17 Przeszukiwanie rekurencyjne
Trzeba sprawdzić, czy poszukiwany element jest w ‘ogonie’. Najlepiej będzie sprawdzić, czy element jest w pierwszym elemencie ‘ogona’.

18 Przeszukiwanie rekurencyjne
Klauzula sprawdzająca ten przypadek wygląda następująco: nalezy( X, [ _|O]) :- nalezy( X, O). Zauważmy, że klauzula ta odwołuje się do samej siebie.

19 Przeszukiwanie rekurencyjne
W takim razie cała nasza ‘funkcja’ wygląda następująco: nalezy( X, [ X| _]). nalezy( X, [ _|O]) :- nalezy(X, O).

20 Przeszukiwanie rekurencyjne
Oczywiście naszą ‘funkcję’ można wykorzystać dwojako: zgodnie z przeznaczeniem, czyli do sprawdzania, czy element należy do listy (nalezy(2,[1,2,3]). uzyskamy true.) wywołując nalezy(X,[1,2,3]). uzyskamy wszystkie elementy z listy [1,2,3] (czyli: X=1; X=2; X=3)

21 Przeszukiwanie rekurencyjne
Istotną kwestią związaną z rekurencją jest to, czy jest ona lewostronna. Z taką sytuacją spotkamy się, jeśli reguła powoduje wywołanie takiego samego celu, jak cel, który ją wywołał. Zobaczmy to na przykładzie

22 Przeszukiwanie rekurencyjne- przykład
Zdefiniujmy taką zależność: osoba(X) :- osoba(Y), matka(X, Y). osoba( adam). I zadajmy zapytanie osoba(X). Jak łatwo zauważyć, uzyskamy pętlę w teorii nieskończoną(w praktyce skończy się nam pamięć)

23 Przeszukiwanie rekurencyjne- przykład
Jak to naprawić? Najłatwiej będzie po prostu zamienić kolejnością klauzule, tak aby rekurencja miała „na czym się zawiesić”. W większości ‘programów’ fakty, takie jak osoba(adam), powinny być umieszczane przed regułami.

24 Przeszukiwanie rekurencyjne
Jakie są predykaty, w których fakty powinny być na końcu? Jednym z takich predykatów jest sprawdzenie, czy podany element jest listą.

25 Przeszukiwanie rekurencyjne
Definicja tego predykatu wygląda następująco: jestLista([ X| Y]) :- jestLista( Y). jestLista( [] ). Polega on na sprawdzeniu, czy ostatni element ‘ogona’ jest listą pustą.

26 Przeszukiwanie rekurencyjne
Niestety ten predykat nie jest odporny na zapętlenie, tzn. jeśli wywołamy jestLista(X). , to wpadniemy w pętlę. Istnieją owszem ‘ulepszenia’ tego predykatu, żeby się nie zapętlał, jednak odbywa się to kosztem osłabienia działania

27 Przeszukiwanie rekurencyjne- przykład polepszenia jestLista()
mocnejestLista([]). mocnejestLista([_|_]).

28 Nawracanie i odcięcie Wyobraźmy sobie rekurencję jako pewnego rodzaju drzewo, tzn. każde kolejne wywołanie jej powoduje utworzenie nowego poziomu w drzewie. Jeżeli w którymś momencie osiągamy coś niepożądanego, to cofamy się w rekurencji do poziomu wyżej anulując dotychczasowe wyniki i wybieramy kolejną opcję.

29 Nawracanie i odcięcie Podobnie działa interpreter Prologa. Podczas działania tworzy on ‘drzewo’ w głąb. Jeżeli coś zawodzi, anuluje ostatni krok i wyniki z nim związane oraz wybiera następną pasującą klauzurę. Działanie to nazywamy nawrotem. Oczywiście może okazać się, że ‘piętro wyżej’ nie ma już wolnych klauzur, więc cofamy się o kolejne piętro do góry…

30 Nawracanie i odcięcie … i w górę i w górę … aż znajdziemy się w korzeniu i nie będzie alternatywnych klauzur do rozważenia. Wówczas osiągniemy wartość false oznaczającą ‘zawód globalny’.

31 Nawracanie i odcięcie Jednakże dzięki nawrotowi możemy uzyskać wszystkie możliwe rozwiązania danego zapytania, np. nalezy(X,[1,2,3]). dzięki mechanizmowi nawrotów wyświetli wszystkie elementy listy [1,2,3].

32 Nawracanie i odcięcie Pewną kontrolę nad nawrotami daje nam bezargumentowy funktor odcięcia wyrażany za pomocą ! . Dojście do niego powoduje, że od chwili wykorzystania w rekurencji klauzuli zawierającej owo odcięcie do chwili dojścia do niego jako podcelu zostają uznane za ostateczne, czyli nie mogą być anulowane.

33 Nawracanie i odcięcie Najlepiej będzie to widać na przykładzie: Załóżmy, że nasza klauzula wygląda następująco: a(X) :- b(X), c(X), !, d(X). Dojście do odcięcia uniemożliwia nawrót do b(X) i c(X), zatem jeśli zawiedzie d(X), to zawiedzie całe a(X).

34 Typowe zastosowanie odcięcia
Można je podzielić na 3 grupy Kiedy chcemy poinformować, że znaleźliśmy odpowiednią regułę. Kiedy chcemy poinformować, że dany cel ma zawieść bez sprawdzenia alternatywnych rozwiązań Kiedy należy zaprzestać generowaniu alternatywnych rozwiązań przez nawracanie

35 Niebezpieczeństwa związane z odcięciem
Posłużmy się przykładem. Mamy predykat stwierdzający ile rodziców ma dana osoba. Z Biblii wiemy, że ileRodzicow( adam, 0) :- !. ileRodzicow( ewa, 0) :- !. Natomiast reszta ludzi: ileRodzicow(X,2).

36 Niebezpieczeństwa związane z odcięciem
Jeżeli zapytamy ileRodzicow( ewa, X) , otrzymamy X=0. Jeżeli zapytamy ileRodzicow( robert, X) , otrzymamy X=2. Jednak jeśli chcemy sprawdzić, czy Ewa ma dwoje rodziców, to zapiszemy ileRodzicow(ewa,2).

37 Niebezpieczeństwa związane z odcięciem
I tu wyskakuje zonk. Okazuje się, że Ewa ma 2 rodziców. Dlaczego? Jest to konsekwencja sposobu przeszukiwania bazy przez Prolog. Jednak można temu zaradzić .

38 Niebezpieczeństwa związane z odcięciem
ileRodzicow( adam, N) :- !, N=0. ileRodzicow( ewa, N) :- !, N=0. ileRodzicow( X, 2). albo ileRodzicow( adam, 0) :- !. ileRodzicow( ewa, 0) :- !. ileRodzicow( X, 2) :- \+(X= adam) , \+(X= ewa).

39 Wejście i wyjście w Prologu- wstęp
Załóżmy, że mamy bazę wiedzy postaci: student(1, ’Ewelina’, 23). student(2, ’Robert’, 40). student(3, ‘Zuza’, 20).

40 Wejście i wyjście w Prologu- czytanie z klawiatury
Do odczytu z klawiatury służy predykat read. Do naszej bazy zdefiniujmy relację czytaj(X) :- read(D), student(D, X). , polegającą na odczytaniu numeru studenta i pokazaniu jego danych.

41 Wejście i wyjście w Prologu- wypisywanie na ekran
Do wypisywania na ekran służy predykat write. Do naszej bazy zdefiniujmy relację pisz(X) :- student( X, Y), write(Y). polegającą na wypisaniu na ekran danych studenta o numerze X.

42 Wejście i wyjście w Prologu- czytanie z pliku
czytajzPliku :- open(‘sciezka_do_pliku',read,X), current_input(W), set_input(X), czytajKod, close(X), set_input(W). czytajKod :- read(T), write(T).

43 Wejście i wyjście w Prologu- czytanie z pliku
czytajzPliku :- open(‘sciezka_do_pliku', read, X), //otworzenie pliku current_input(W), //zapis strumienia wejścia do W set_input(X), //zmiana wejścia na X czytajKod, //wykonanie czytajKod close(X), //zamknięcie wejścia X set_input(W). //zmiana wejścia na W czytajKod :- read(T), write(T).

44 Wejście i wyjście w Prologu- czytanie z pliku
Domyślnym strumieniem wejściowym jest klawiatura. Jednakże czytajKod odczytuje tylko jeden wiersz z pliku. Aby odczytywać ich więcej należy go lekko zmodyfikować. czytajKod :- read(T), wykonaj(T). wykonaj( end_of_file ) :- !. wykonaj(T) :- write(T), nl, czytajKod. // nl- nowa linia

45 Wejście i wyjście w Prologu- zapis do pliku
piszdoPliku :- open(‘sciezka_do_pliku',write,X), current_output(W), set_output(X), piszKod, close(X), set_output(W). piszKod :- write(T), nl.

46 Wejście i wyjście w Prologu- zapis do pliku
piszdoPliku :- open(‘sciezka_do_pliku',write,X), //otworzenie pliku current_output(W), //zapis aktualnego wyjścia do W set_output(X), //zmiana aktualnego wyjścia na X piszKod, //wykonanie piszKod close(X), //zamkniecie wyjścia X set_output(W). //zmiana wyjścia na W piszKod :- write(T), nl.

47 Wejście i wyjście w Prologu- zapis do pliku
Domyślnym strumieniem wyjściowym jest ekran. Oczywiście można zmodyfikować piszKod tak, aby końcem zapisu było wpisanie ‘pa’: piszKod :- read(X), \+(X=‘pa'), write(X), nl, flush, PiszKod. //flush czyści bufor

48 Predykaty wbudowane Predykaty wbudowane możemy podzielić na kilka kategorii, m.in.: Sukces i porażka Klasyfikacja termów Wpływ na nawracanie Równość Wejście i wyjście Obsługa plików Arytmetyka Porównanie I wiele, wiele innych …

49 Predykaty wbudowane- Sukces i porażka
Do tych predykatów zaliczamy: true – ten cel nigdy nie zawodzi. Nie jest on niezbędny, gdyż klauzury i cele można tak ustawić, żeby był zbędny. Jednak dla wygody go zdefiniowano. fail – ten cel zawsze zawiedzie. Przydatny w parze z odcięciem albo gdy chcemy jawnie wywołać nawracanie.

50 Predykaty wbudowane- Klasyfikacja termów
var(X) – nie zawodzi, gdy X jest zmienną nieukonkretnioną nonvar(X) – przeciwieństwo var(X) atom(X) – nie zawodzi, jeśli X jest atomem number(X) – nie zawodzi, jeśli X jest liczbą atomic(X) – nie zawodzi, jeśli X jest liczbą lub atomem

51 Predykaty wbudowane- Klasyfikacja termów
integer(X) – jest spełniony, jeśli X jest stałą lub zmienną całkowitą real(X) – jest spełniony, jeśli X jest stałą lub zmienną stałoprzecinkową

52 Predykaty wbudowane- Wpływ na nawracanie
repeat – to dodatkowa metoda generowania wielu rozwiązań przez nawracanie ! – na odcięcie można patrzeć jako na predykat wbudowany zatwierdzający pewne wybory dokonane przez interpreter.

53 Predykaty wbudowane- Równość
X=Y – gdy Prolog napotyka taki cel, stara się zrównać X z Y dopasowując je do siebie. Jeśli to możliwe, to cel jest uzgodniony, w przeciwnym wypadku zawodzi. X==Y – powoduje on ‘lepsze’ zrównanie X i Y . Jeśli X==Y, to X=Y, ale nie odwrotnie.

54 Predykaty wbudowane- Wejście i wyjście
get_char(X) – nie zawodzi, jeśli X można dopasować do następnego znaku z bieżącego strumienia wejściowego. Może być uzgodniony tylko raz! read(X) – odczytuje term z bieżącego strumienia wejściowego i dopasowuje go do X. Musi kończyć się kropką.

55 Predykaty wbudowane- Wejście i wyjście
put_char(X) – wpisuje do bieżącego strumienia wyjściowego znak X nl – wpisuje do bieżącego strumienia wyjściowego sekwencję powodującą przejście do nowego wiersza. write(X) – powoduje zapisanie termu X do bieżącego strumienia wyjściowego.

56 Predykaty wbudowane- Obsługa plików
open(X,Y,Z) – otwiera plik o nazwie X. Jeśli Y jest read, to w trybie odczytu, w przeciwnym razie w trybie zapisu. Z oznacza strumień, do którego należy używać podczas odwoływania się do pliku close(X) – używany do zamknięcia strumienia X

57 Predykaty wbudowane- Obsługa plików
set_input(X) – ustawia bieżący strumień wejściowy na wskazany przez X set_output(X) – ustawia bieżący strumień wyjściowy na wskazany przez X current_input(X) – cel jest uzgodniony, jeśli nazwa bieżącego strumienia wejściowego pasuje do X. W przeciwnym razie zawodzi current_output(X) - cel jest uzgodniony, jeśli nazwa bieżącego strumienia wyjściowego pasuje do X. W przeciwnym razie zawodzi

58 Predykaty wbudowane- Arytmetyka
X is Y X + Y X - Y X * Y X / Y X mod Y Pozostawię to bez omówienia 

59 Predykaty wbudowane- Porównanie
X = Y X < Y X > Y X >= Y X =< Y To również pozostawię bez omówienia 

60 Predykaty wbudowane- Porównanie
Zasady decydujące, które z termów są mniejsze: Wszystkie zmienne nieukonkretnione są mniejsze od wszystkich liczb zmiennoprzecinkowych. Te natomiast są mniejsze od wszystkich liczb całkowitych, które są mniejsze od wszystkich atomów, które są mniejsze od jakichkolwiek struktur

61 Predykaty wbudowane- Porównanie
Zasady decydujące, które z termów są mniejsze: W przypadku dwóch niepowiązanych, nieukonkretnionych zmiennych zawsze jedna z nich będzie mniejsza od drugiej Porównywanie liczb zmiennoprzecinkowych i całkowitych odbywa się zawsze zgodnie z intuicją

62 Predykaty wbudowane- Porównanie
Zasady decydujące, które z termów są mniejsze: Atom jest mniejszy od innego, jeśli występuje przed nim w zwykłym porządku słownikowym Jedna struktura jest mniejsza od drugiej, jeśli jej funktor ma mniej argumentów. Jeśli dwie struktury mają tyle samo argumentów, to mniejsza jest ta, której funktor jest mniejszy. Jeśli dwie struktury mają tyle samo argumentów i takie same funktory, to bada się po kolei pierwszy z pierwszym, drugi z drugim itd.

63 Predykaty wbudowane- Porównanie
Y – nie zawodzi, jeśli X jest mniejszy od Y w porządku opisanym na poprzednich slajdach. Y – nie zawodzi, jeśli X jest większy od Y w porządku opisanym na poprzednich slajdach. Y – nie zawodzi, jeśli X jest większy lub równy Y w porządku opisanym na poprzednich slajdach. Y – nie zawodzi, jeśli X jest mniejszy lub równy Y w porządku opisanym na poprzednich slajdach.

64 Przykłady

65 Dziękujemy za uwagę 


Pobierz ppt "Kunikowska Ewelina Grzechowski Ariel"

Podobne prezentacje


Reklamy Google