Wprowadzenie do Sztucznej Inteligencji Laboratorium lista 0.4 Elementy języka Prolog: metaprogramowanie i struktury danych. Przemysław Kobylański

Podobne dokumenty
Programowanie w Logice

Wprowadzenie do Sztucznej Inteligencji Laboratorium lista 0.2 Elementy języka Prolog: reguły i rekurencja. Przemysław Kobylański

Programowanie w Logice Struktury danych (Lista 2)

Wprowadzenie do Sztucznej Inteligencji Laboratorium lista 0.1 Elementy języka Prolog: fakty i zapytania. Przemysław Kobylański

Programowanie w Logice Przykłady programów. Przemysław Kobylański

PODSTAWY SZTUCZNEJ INTELIGENCJI

PROLOG INNE PRZYKŁADY MACIEJ KELM

Programowanie w Logice Gramatyki metamorficzne. Przemysław Kobylański na podstawie [CM2003] i [SS1994]

Programowanie w Logice Środowisko programowania i dialog z systemem (Lista 0)

Programowanie w logice

Podstawy Sztucznej Inteligencji (PSZT)

Programowanie w Logice

Metoda Tablic Semantycznych

Programowanie w logice Prolog 2

PROLOG. Prolog. Programowanie, W.F. Clocksin, C.S. Mellish, HELION Prolog, język sztucznej inteligencji, Eugeniusz Gatnar, Katarzyna Stąpor, Wyd.

Prolog 2 (Filip Wroński, Łukasz Betkowski, Paweł Świerblewski, Konrad Kosmatka)

Dana jest baza: kobieta(katarzyna). kobieta(anna). kobieta(maria). kobieta(marianna). kobieta(marta). Zdefiniujemy predykat kobiety/0 następująco:

Programowanie w Logice

I. Podstawowe pojęcia i oznaczenia logiczne i mnogościowe. Elementy teorii liczb rzeczywistych.

Projekt 4: Programowanie w logice

JAVAScript w dokumentach HTML (1) JavaScript jest to interpretowany, zorientowany obiektowo, skryptowy język programowania.

Programowanie w logice

Andrzej Wiśniewski Logika I Materiały do wykładu dla studentów kognitywistyki. Wykłady 12 i 13. Dowód i dowodzenie w KRP. Tezy KRP

Wprowadzenie do Prologa

Język C zajęcia nr 11. Funkcje

Algorytmy i Struktury Danych, 9. ćwiczenia

Podstawy Sztucznej Inteligencji (PSZT)

Laboratorium przedmiotu Paradygmaty Programowania

Składnia rachunku predykatów pierwszego rzędu

Wstęp do Informatyki i Programowania Laboratorium: Lista 0 Środowisko programowania

Klasyczny rachunek predykatów

Struktury danych: stos, kolejka, lista, drzewo

Listy, krotki, słowniki, funkcje

Przypomnij sobie krótki wstęp do teorii grafów przedstawiony na początku semestru.

Adam Meissner.

Wstęp do programowania

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie

Systemy ekspertowe i ich zastosowania. Katarzyna Karp Marek Grabowski

Algorytmy i Struktury Danych

Celem ćwiczenia jest zapoznanie się z podstawowymi możliwościami języka Prolog w zakresie definiowania faktów i reguł oraz wykonywania zapytań.

Porządek symetryczny: right(x)

Obliczenia na stosie. Wykład 9. Obliczenia na stosie. J. Cichoń, P. Kobylański Wstęp do Informatyki i Programowania 266 / 303

Adam Meissner STUCZNA INTELIGENCJA

Programowanie deklaratywne

EGZAMIN - Wersja A. ALGORYTMY I STRUKTURY DANYCH Lisek89 opracowanie kartki od Pani dr E. Koszelew

Algorytmy sortujące i wyszukujące

1. Składnia. Logika obliczeniowa - zadania 1 SKŁADNIA Teoria

Programowanie logiczne a negacja

Programowanie deklaratywne

Programowanie deklaratywne

Elementy języka Prolog

Semantyka rachunku predykatów

Wstęp do logiki. Klasyczny Rachunek Predykatów I

REKURENCJA W JĘZYKU HASKELL. Autor: Walczak Michał

1. Wstęp do logiki. Matematyka jest nauką dedukcyjną. Nowe pojęcia definiujemy za pomocą pojęć pierwotnych lub pojęć uprzednio wprowadzonych.

Deklarowania faktów dotyczących obiektów i związków między nimi. Definiowania reguł dotyczących obiektów i związków między nimi.

Wykład 11b. System aksjomatyczny Klasycznego Rachunku Predykatów. Aksjomaty i reguły inferencyjne

Wprowadzenie do logiki Zdania, cz. III Język Klasycznego Rachunku Predykatów

Programowanie deklaratywne

Cw.12 JAVAScript w dokumentach HTML

Programowanie w logice Wykład z baz danych dla

Dynamiczny przydział pamięci w języku C. Dynamiczne struktury danych. dr inż. Jarosław Forenc. Metoda 1 (wektor N M-elementowy)

Adam Meissner SZTUCZNA INTELIGENCJA

Sortowanie. Kolejki priorytetowe i algorytm Heapsort Dynamiczny problem sortowania:

Problem. Uzgadnianie wyrażeń rachunku predykatów. Instancja wyrażenia. Podstawienie termu za zmienną. Joanna Józefowska

mgr inż. Adam Pinkowski

METODA SYMPLEKS. Maciej Patan. Instytut Sterowania i Systemów Informatycznych Uniwersytet Zielonogórski

Uzgadnianie formuł rachunku predykatów

Informatyka klasa III Gimnazjum wymagania na poszczególne oceny

Zadanie projektowe nr 1

Języki programowania deklaratywnego

Wykład 11a. Składnia języka Klasycznego Rachunku Predykatów. Języki pierwszego rzędu.

Metoda tabel semantycznych. Dedukcja drogi Watsonie, dedukcja... Definicja logicznej konsekwencji. Logika obliczeniowa.

Wykład 2. Relacyjny model danych

Algorytmy i struktury danych

Struktura danych. Sposób uporządkowania informacji w komputerze. Na strukturach danych operują algorytmy. Przykładowe struktury danych:

Optymalizacja systemów

Zaawansowane aplikacje WWW - laboratorium

Podstawowe zapytania SELECT (na jednej tabeli)

METODY DOWODZENIA TWIERDZEŃ I AUTOMATYZACJA ROZUMOWAŃ

Wstęp 5 Rozdział 1. Podstawy relacyjnych baz danych 9

TECHNOLOGIE INTERNETOWE WYKŁAD 6. JavaScript Funkcje i obiekty

Definicje wyższego poziomu

MS Excel 2007 Kurs zaawansowany Obsługa baz danych. prowadzi: Dr inż. Tomasz Bartuś. Kraków:

Język rachunku predykatów Formuły rachunku predykatów Formuły spełnialne i prawdziwe Dowody założeniowe. 1 Zmienne x, y, z...

Przeszukiwanie z nawrotami. Wykład 8. Przeszukiwanie z nawrotami. J. Cichoń, P. Kobylański Wstęp do Informatyki i Programowania 238 / 279

dodatkowe operacje dla kopca binarnego: typu min oraz typu max:

Drzewo binarne BST. LABORKA Piotr Ciskowski

PRZYKŁADOWY TEST EGZAMINACYJNY

Andrzej Wiśniewski Logika I Materiały do wykładu dla studentów kognitywistyki. Wykład 9. Koniunkcyjne postacie normalne i rezolucja w KRZ

WYMAGANIA EDUKACYJNE Z INFORMATYKI dla klasy III gimnazjalnej, Szkoły Podstawowej w Rychtalu

Statyczne i dynamiczne predykaty

CLP Programowanie logiczne z ograniczeniami.

Optymalizacja systemów

Programowanie w języku Python. Grażyna Koba

Podstawy języka PROLOG

Wykład 3. Złożoność i realizowalność algorytmów Elementarne struktury danych: stosy, kolejki, listy

RACHUNEK ZDAŃ 7. Dla każdej tautologii w formie implikacji, której poprzednik również jest tautologią, następnik także jest tautologią.

Dariusz Banasiak. Instytut Informatyki, Automatyki i Robotyki. Politechniki Wrocławskiej

Tablice. Jones Stygar na tropie zmiennych

Transkrypt:

Wprowadzenie do Sztucznej Inteligencji Laboratorium lista 0.4 Elementy języka Prolog: metaprogramowanie i struktury danych Przemysław Kobylański Część I Wprowadzenie 1 Metapredykaty Argumentem wywołania predykatu może być warunek do sprawdzenia. Na wcześniejszych listach zadań korzystaliśmy między innymi z predykatu \+ Warunek, który jest metapredykatem wyrażającym negację. 1.1 Przykład Predykat forall/2 jest metapredykatem. Jego argumentami są dwa warunki: generator warunek dostarczający kolejne wartości, walidator warunek sprawdzający wygenerowane wartości. Predykat forall(generator, Walidator) jest spełniony gdy wszystkie wartości wygenerowane przez Generator spełniają warunek Walidator. Krótki dialog:?- forall(member(x, [2, 4, 6, 8]), 0 =:= X mod 2). true.?- forall(member(x, [2, 4, 5, 8]), 0 =:= X mod 2). 2 Kolekcjonowanie wyników Kolejne wyniki (odpowiedzi na zadane pytanie) można oglądać naciskając średnik po wydrukowaniu przez system Prolog każdego z nich. Jeśli odpowiedzi jest wiele, można stosując drukowanie i nawroty wyświetlić je wszystkie bez potrzeby żmudnego naciskania średnika:?- append(x, Y, [1, 2, 3, 4, 5]), write(x - Y), nl, fail. []-[1,2,3,4,5] [1]-[2,3,4,5] [1,2]-[3,4,5] 1

[1,2,3]-[4,5] [1,2,3,4]-[5] [1,2,3,4,5]-[] Często istnieje jednak konieczność zebrania wszystkich wyników na liście celem ich dalszego przetwarzania, a nie tylko wydrukowania ich na ekranie. Niech T będzie termem zawierającym zmienne a G warunkiem generującym wartości dla tych zmiennych. Predykat findall(t, G, L) tworzy listę wszystkich przykładów termu T powstałych przez podstawianie za zmienne z termu T wartości wygenerowanych warunkiem G. Na liście L mogą pojawić się wielokrotnie te same termy. Jeśli chcemy kolekcjonować termy bez powtórzeń (utworzyć ich zbiór a nie listę), należy użyć predykatu setof(t, G, L). Lista utworzona przez predykat setof/3 nie tylko nie zawiera powtórzeń ale również jest uporządkowana zgodnie z liniowym porządkiem na termach @<. Przy predykacie setof/3 trzeba uważać na zmienne, które występują w warunku G ale nie występują w termie T. Aby faktycznie zebrać wszystkie przykłady termu należy zastosować kwantyfikator egzystencjalny. Zapis X^G, gdzie X jest zmienną występującą w warunku G ale nie w termie T, należy rozumieć jako ( X)G. Warunek findall/3 odpowiada warunkowi bagof/3, przy czym zachodzą następujące dwie różnice: 1. Jeśli lista przykładów jest pusta, to findall/3 nie zawodzi, natomiast bagof/3 zawodzi. 2. bagof/3 umożliwia korzystania z kwantyfikatora egzystencjalnego a findall/3 nie pozwala na to. Więcej o znajdowaniu wszystkich rozwiązań w rozdziale podręcznika: Finding all Solutions to a Goal. 2.1 Przykłady p(b). p(a). p(b). p(a).?- findall(x, p(x), L). L = [b, a, b, a].?- setof(x, p(x), L). L = [a, b].?- findall(k, (between(-2, 2, I), K is I*I), L). L = [4, 1, 0, 1, 4].?- setof(k, (between(-2, 2, I), K is I*I), L). I = -2, L = [4] ; I = -1, L = [1] ; I = 0, 2

L = [0] ; I = 1, L = [1] ; I = 2, L = [4].?- setof(k, I^(between(-2, 2, I), K is I*I), L). L = [0, 1, 4].?- findall(x, (member(x, [1, 2, 3]), X > 4), L). L = [].?- bagof(x, (member(x, [1, 2, 3]), X > 4), L).?- bagof(x, (member(x, [1, 2, 3]), X > 2), L). L = [3]. 3 Metaprogramowanie Wykorzystywanie metapredykatów bardzo upraszcza zapis programów gdyż dostarcza ogromną moc języka. Możliwe jest w nim budowanie termu, który stanie się warunkiem do udowodnienia:?- Warunek =.. [append, X, Y, [1, 2, 3]], Warunek. Warunek = append([], [1, 2, 3], [1, 2, 3]), X = [], Y = [1, 2, 3] ; Warunek = append([1], [2, 3], [1, 2, 3]), X = [1], Y = [2, 3] ; Warunek = append([1, 2], [3], [1, 2, 3]), X = [1, 2], Y = [3] ; Warunek = append([1, 2, 3], [], [1, 2, 3]), X = [1, 2, 3], Y = [] ; W powyższym przykładzie użyto predykat =../2, który służy do konstruowania i rozkładania termów na listę złożoną z funktora i jego argumentów:?- a =.. X. X = [a].?- f(a) =.. X. X = [f, a].?- f(a, g(b)) =.. X. X = [f, a, g(b)].?- X =.. [f, a, g(b), c]. X = f(a, g(b), c). 3

3.1 Przykłady 3.1.1 Łamigłówka Każdy mieszkaniec wyspy jest albo rycerzem (zawsze mówi prawdę) albo łotrem (zawsze kłamie). Pewnego dnia B stwierdził: "A powiedział o sobie, że jest łotrem". Kim jest B? rycerz(rycerz). lotr(lotr). powiedzial(rycerz, X) :- X. powiedzial(lotr, X) :- \+ X.?- powiedzial(b, powiedzial(a, lotr(a))). B = lotr. 3.1.2 Interpreter Prologu w Prologu Predykat clause/2 umożliwia pobieranie klauzul składających się na program w Prologu. Warunek clause(head, Body) jest spełniony gdy dla danej formuły atomowej Head istnieje klauzula o głowie unifikowalnej z Head i ciele (treści) unifikowalneym z Body. W wyniku nawrotów podstawiane będą kolejne klauzule o głowach pasujących do Head. app([], X, X). app([x Y1], Y2, [X Z]) :- app(y1, Y2, Z). interpreter(true). interpreter((g1, G2)) :- interpreter(g1), interpreter(g2). interpreter(a) :- A \= true, A \= (_, _), clause(a, B), interpreter(b). [debug]?- interpreter(app(x, Y, [1, 2, 3])). X = [], Y = [1, 2, 3] ; X = [1], Y = [2, 3] ; X = [1, 2], Y = [3] ; X = [1, 2, 3], Y = [] ; Powyższy interpreter obsługuje tylko predykaty zdefiniowane klauzulami, których ciała są warunkiem true (gdy fakt) albo jedną lub koniunkcją formuł atomowych połączonych przecinkami (gdy reguła). 4

4 Struktury danych W Prologu dostępne są moduły definiujące między innymi następujące struktury danych: zbiory uporządkowane kopce (kolejki priorytetowe) drzewa czerwono-czarne 4.1 Zbiory uporządkowane Zbiory można reprezentować w Prologu w postaci list uporządkowanych bez powtarzających się elementów. Aby skorzystać z dostępnych w Prologu predykatów na zbiorach uporządkowanych, należy zaimportować moduł ordsets w pliku źródłowym dyrektywą: :- use_module(library(ordsets)). albo zadając systemowi sc Prolog pytanie:?- use_module(library(ordsets)). Przykład dialogu o zbiorach uporządkowanych:?- list_to_ord_set([1, 2, 3, 2, 3, 4], X), ord_memberchk(2, X). X = [1, 2, 3, 4].?- list_to_ord_set([1, 2, 3, 2, 3, 4], X), ord_memberchk(5, X).?- list_to_ord_set([1, 2, 1], X1), list_to_ord_set([2, 1, 3], X2), ord_intersection(x1, X2, X). X1 = X, X = [1, 2], X2 = [1, 2, 3].?- list_to_ord_set([1, 2, 1], X1), list_to_ord_set([2, 1, 3], X2), ord_union(x1, X2, X). X1 = [1, 2], X2 = X, X = [1, 2, 3].?- list_to_ord_set([1, 2, 1], X1), list_to_ord_set([2, 1, 3], X2), ord_symdiff(x1, X2, X). X1 = [1, 2], X2 = [1, 2, 3], X = [3]. Więcej o zbiorach uporządkowanych w dodatku podręcznika: library(ordsets): Ordered set manipulationl. 4.2 Drzewa czerwono-czarne Aby skorzystać z dostępnych w Prologu predykatów na drzewach czerwono-czarnych, należy zaimportować moduł rbtrees w pliku źródłowym dyrektywą: :- use_module(library(rbtrees)). 5

albo zadając systemowi sc Prolog pytanie:?- use_module(library(rbtrees)). Elementy wstawiane są do drzewa czerwono-czarnego wraz z kluczami względem których drzewo jest uporządkowane. Najprościej stworzyć drzewo czerwono-czarne tak jak w poniższym przykładzie, tj. przez zamianę listy zawierającej pary Klucz - Element:?- list_to_rbtree([2-a, 0-b, 5-c, 1-d], RB0), rb_del_min(rb0, MinKlucz, MinElement, RB1), rb_del_max(rb1, MaxKlucz, MaxElement, RB2). RB0 = t(black(, _G1908, _G1909, ), black(black(black(, _G1908, _G1909, ), 0, b, black(, _G1908, _G1909, )), 1, d, black(black(, _G1908, _G1909, ), 2, a, red(black(, _G1908, _G1909, ), 5, c, black(, _G1908, _G1909, ))))), MinKlucz = 0, MinElement = b, RB1 = t(black(, _G1908, _G1909, ), black(black(black(, _G1908, _G1909, ), 1, d, black(, _G1908, _G1909, )), 2, a, black(black(, _G1908, _G1909, ), 5, c, black(, _G1908, _G1909, )))), MaxKlucz = 5, MaxElement = c, RB2 = t(black(, _G1908, _G1909, ), black(red(black(, _G1908, _G1909, ), 1, d, black(, _G1908, _G1909, )), 2, a, black(, _G1908, _G1909, ))). W powyższym przykładzie: RB0 jest drzewem czerwono-czarnym zawierającym pary 2-a, 0-b, 5-c, 1-d, RB1 jest drzewem czerwono-czarnym powstałym z RB0 przez usunięcie elementu o najmniejszym kluczu, RB2 jest drzewem czerwono-czarnym powstałym z RB1 przez usunięcie elementu o największym kluczu. Więcej o drzewach czerwono-czarnych w opisie biblioteki: rbtrees.pl Red black trees. 4.3 Kopce/kolejki priorytetowe Celem szybkiego dostępu do minimalnego elementu i usuwania go ze zbioru, można użyć strukturę kopca (kolejki priorytetowej). Aby skorzystać z dostępnych w Prologu predykatów na kopcach (kolejkach priorytetowych), należy zaimportować moduł heaps w pliku źródłowym dyrektywą: :- use_module(library(heaps)). albo zadając systemowi sc Prolog pytanie:?- use_module(library(heaps)). Elementy (klucze) w kopcu (kolejce priorytetowej) przechowywane są w postaci par Priorytet - Klucz, gdzie Priorytet jest wartością względem której Klucz jest uporządkowany w kopcu (kolejce priorytetowej). W poniższym przykładzie wstawiono trzy klucze e1, e2, e3 o priorytetach, odpowiednio, 20, 10, 30 a następnie usunięto z utworzonego kopca (kolejki priorytetowej) Klucz o najmniejszym priorytecie: 6

?- list_to_heap([], H0), add_to_heap(h0, 20, e1, H1), add_to_heap(h1, 10, e2, H2), add_to_heap(h2, 30, e3, H3), get_from_heap(h3, Priorytet, Klucz, H4). H0 = heap(nil, 0), H1 = heap(t(e1, 20, []), 1), H2 = heap(t(e2, 10, [t(e1, 20, [])]), 2), H3 = heap(t(e2, 10, [t(e3, 30, []), t(e1, 20, [])]), 3), Priorytet = 10, Klucz = e2, H4 = heap(t(e1, 20, [t(e3, 30, [])]), 2). W powyższym przykładzie: H0 jest początkowo pustym kopcem, H1 jest kopcem zawierającym jedynie klucz e1, H2 jest kopcem zawierającym klucze e1 i e2, H3 jest kopcem zawierającym klucze e1, e2 i e3, H4 jest kopcem powstałym z H3 po usunięciu klucza o najmniejszym priorytecie. Więcej o kopcach/kolejkach priorytetowych w opisie biblioteki: heaps.pl heaps/priorit queues. Część II Zadania i polecenia Polecenie 1 Załóżmy, że dana jest baza o zarobkach pracowników w postaci następujących faktów: pracownik(abacki, 3700). pracownik(babacki, 5200). pracownik(cabacki, 2500). Skompiluj powyższe fakty (np. umieszczając je w pliku baza.pl i kompilując ją). Jeśli chcemy poznać nazwiska pracowników w kolejności rosnących zarobków, możemy zrobić to następującym pytaniem:?- setof(zarobek - Pracownik, pracownik(pracownik, Zarobek), Zbior), member(_ - Nazwisko, Zbior). Zbior = [2500-cabacki, 3700-abacki, 5200-babacki], Nazwisko = cabacki ; Zbior = [2500-cabacki, 3700-abacki, 5200-babacki], Nazwisko = abacki ; Zbior = [2500-cabacki, 3700-abacki, 5200-babacki], Nazwisko = babacki. 7

W powyższym przykładzie lista Zbior jest uporządkowaną listą par Zarobek - Pracownik. Pary takie uporządkowane są według następującego porządku liniowego: Z 1 P 1 < Z 2 P 2 (Z 1 < Z 2 ) gdzie @</2 jest liniowym porządkiem na termach. Zadanie 2 Elementy macierzy: A = zapisano w postaci faktów tab(i, j, a ij ): 7 2 0 2 5 3 4 3 10 1 4 2 (Z 1 = Z 2 P 1 @<P 2 ), tab(1, 1, 5). tab(1, 2, 3). tab(1, 3, 4). tab(1, 4, 3). tab(2, 1, 7). tab(2, 2, 2). tab(2, 3, 0). tab(2, 4, -2). tab(3, 1, 10). tab(3, 2, -1). tab(3, 3, -4). tab(3, 4, 2). Niech warunek siodlo(i, J) wyraża, to że element a ij tak zadanej macierzy jest punktem siodłowym, tj. zachodzi: Napisz predykat siodlo(i, J). ( k )( l ) a kj a ij a il 1. Czy potrafisz tak napisać predykat siodlo(i, J) aby znajdował wszystkie punkty siodłowe przykładowej macierzy A w mniej niż 100 wnioskowań (użyj predykat time/1 do pomiaru). 2. Wskazówka: użyj negację. Przykład pomiaru liczby wnioskowań przy wyznaczaniu wszystkich punktów siodłowych:?- time((siodlo(_, _), fail)). % 63 inferences, 0.000 CPU in 0.000 seconds (84% CPU, 1702703 Lips) Zadanie 3 Załóżmy, że formuły iap(e1, N, E2) wyrażają fakt, że element E1 jest częścią (isa-part) elementu E2 i występuje w nim w N egzemplarzach (np. iap(kolo, 2, rower). Poniżej przedstawiono kilka faktów opisujących obiekt o1 złożony z obiektów o2, o3, o4, o5: iap(o2, 2, o1). iap(o3, 3, o1). iap(o4, 2, o3). iap(o5, 5, o3). Powyższe fakty można zrozumieć następująco: 1. Aby zmontować jedną sztukę o1 należy połączyć ze sobą dwie sztuki o2 i trzy sztuki o3. 8

2. Aby zmontować jedną sztukę o3 należy połączyć ze sobą dwie sztuki o4 i pięć sztuk o5. 3. Elementy o2, o4 i o5 nie są montowane zatem należy je zakupić. Napisz predykat zamowienie(produkt, N, Lista), który planuje wielkość zakupów na potrzeby wyprodukowania N egzemplarzy Produktu. Zamówienie powinno być w postaci listy o elementach postaci Liczba * Element, wyrażających potrzebę zamówienia danej liczby elementów. Przykładowy dialog:?- zamowienie(o1, 10, X). X = [20*o2, 60*o4, 150*o5].?- zamowienie(o3, 50, X). X = [100*o4, 250*o5]. 9