====== KRR: Prolog - baza wiedzy ====== ===== Historia ===== Prolog to system realizujący użycie logiki jako paradygmatu "programowania" (//PROgrammation en LOGique, PROgramming in LOGic//). Wybrane informacje: * podstawy teoretyczne: logika ([[wp>George_Boole]],[[wp>Gottlob_Frege]],[[wp>Alfred_Tarski]], i inni), [[wp>J._Alan_Robinson]] (rezolucja), [[wp>]] (University of Edinburgh) * implementacje: [[wp>Alain_Colmerauer]], (University of Aix-Marseille), 1972; [[wp>David_H._D._Warren]] (University of Edinburgh) 1977 Więcej wskazówek związanych z uczeniem się Prologu można znaleźć na [[pl:prolog:prolog_lab#przydatne_materialy|głównej stronie laboratorium]]. //Uwaga:// nie należy za bardzo przejmować się hasłem o Prologu w Wikipedii -- jest //źle// napisane! ===== Prolog jako system reprezentowania wiedzy i wnioskowania ===== Prolog dostarcza //metodę reprezentacji wiedzy// (klauzule Horna), która pozwala na opis i budowę //bazy wiedzy// (ang. //knowledge base//). Prolog jest wyposażony w system //automatycznego wnioskowania// (ang. //automated reasoning//), który pozwala w szczególności na automatyczne wyszukiwanie rozwiązań problemów/zadań opisanych przy pomocy bazy wiedzy. Praca z systemem obejmuje: - opis problemu (KB), - sformułowanie celu (ang. //goal//) czy też pytania (ang. //query//), - automatyczne wyszukanie rozwiązania. Co za tym idzie Prolog nie jest "językiem programowania" ile systemem rozwiązywania problemów, obejmującym język ich opisu. ===== SWI Prolog ===== Współcześnie jest dostępnych szereg implementacji Prologu, w tym swobodnie dostępne kompilatory Prologu: * Jan Wielemaker, //SWI-Prolog//, http://www.swi-prolog.org * LIACC/Universidade do Porto, OPPE Sistemas/UFRJ, //YAP//, http://www.ncc.up.pt/~vsc/Yap/ * Daniel Diaz, //GNU-Prolog//, http://gnu-prolog.inria.fr W czasie zajęć będzie się pracować w środowisku SWI. Podstawowym interfejsem w SWI jest powłoka. W powłoce pracuje się podobnie jak w powłoce unixowej, oczywiście z uwzględnieniem specyfiki Prologu. ==== Uruchamianie powłoki ==== **Ćwiczenie** Unix/GNU/Linux: Proszę otworzyć okno terminala, np. ''xterm'' i uruchomić w nim powłokę SWI przez polecenie ''swipl'' (może też być dostępny przez polecenie ''pl''). Windows: uruchomić za pomoc ikony, menu, itp. UWAGA: każda //linia kodu// w Prologu musi się kończyć kropką, podobnie linia, polecenie w powłoce! Proszę sprawdzić działanie systemu pomocy, przez predykat ''help.'', a następnie przeczytać opis do predykatu ''consult/1''. Proszę wyjść z powłoki przez ''halt.'' Proszę ponownie uruchomić powłokę SWI. Przy pomocy jakiej kombinacji klawiszy można wyjść z powłoki unixowej - analogiczenie w SWI? ==== Środowisko pracy ==== SWI dostarcza przede wszystkim zaawansowanej powłoki, wyposażonej w bibliotekę //GNU ReadLine//. Cennym uzupełnieniem jest edytor GNU Emacs ze środowiskiem edycyjnym (trybem) //[[http://packages.debian.org/stable/prolog-el|prolog.el]]//. SWI w wersji rozszerzonej o środowisko XPCE dostarcza również narzędzi programistycznych, takich jak wbudowany edytor //emacs//. Aby z niego skorzystać należy zamiast ''swipl'' wywołać ''xpce'' a potem w powłoce Prologu ''emacs.''. **Ćwiczenie** Sprawdzić działanie systemu pracy z linią poleceń (GNU Readline): historia, dopełnianie, skrótu klawiaturowe. Przeglądnąć tryb pracy w GNU Emacs i edytor PCE Emacs (uruchomić SWI Prolog przez ''xpce''). ===== Fakty w bazie wiedzy ===== Baza wiedzy obejmuje dwa rodzaje sformułowań, prostszym z nich są fakty. **Ćwiczenie** Proszę przyjrzeć się poniższej, prostej bazie wiedzy. rodzic(kasia,robert). rodzic(tomek,robert). rodzic(tomek,eliza). kobieta(kasia). kobieta(eliza). mezczyzna(tomek). mezczyzna(robert). Proszę uruchomić wybrany zewnętrzny edytor i wpisać w nim podobny tekst, dotyczący własnej (albo innej) rodziny. Mniej ambitni mogą po prostu przepisać... Program należy zapisać w pliku //fam1.pl//. Inny przykład //pf1.pl//: woman(mia). woman(jody). woman(yolanda). playsAirGuitar(jody). party. ==== Wczytywanie bazy wiedzy ==== Aby użyć bazy wiedzy należy w powłoce załadować plik przy pomocy predykatu ''consult/1'' (skrót: ''[nazwa].'') Operację tę należy powtarzać po każdej modyfikacji pliku bazy wiedzy. **Ćwiczenie** W powłoce SWI należy wczytać powyższe pliki: ?- [fam1]. ?- [pf1]. Zawarta w nich wiedza dodawana do bazy wiedzy dostępnej z powłoki SWI. ?- listing. ===== Proste pytania ===== Dysponując bazą wiedzy można zadawać pytania/cele. Czy Kasia jest kobietą? ?- kobieta (kasia). Czy Mia jest kobietą? Czy Tomek jest rodzicem Elizy? Uwaga: Prolog zawsze "wie". Ale wie dokładnie tyle ile mu powiemy: Czy Kopernik jest kobietą? Czy Vincent jest kobietą? Nazywamy to //closed world assumption//. Inny ogólniejszy rodzaj pytań. Czy znasz/istnieją jakieś Kobiety? ?- kobieta(_). Czy Tomek jest rodzicem? ===== Generowanie rozwiązań ===== Poza odpowiadaniem na pytania Prolog potrafi wyszukiwać - generować rozwiązania. Jakie znasz/są/istnieją kobiety? ?- kobieta(Kto). Kto jest rodzicem? ?- rodzic(R,_). ===== Pytania złożone ===== Czy znasz rodziców, którzy mają synów-dzieci, które są mężczyznami? ?- rodzic(R,S),mezczyzna(S). Kto jest ojcem, tj. rodzicem, który jest mężczyzną: ?- rodzic(R,S),mezczyzna(R). ===== Reguły i wnioskowanie ===== Reguły pozwalają na uchwycenie pewnych prawidłowości i generowanie w procesie wnioskowania nowej wiedzy, nie reprezentowanej explicite. Dopisz do poprzednich plików i zapisz pod nową nazwą, następnie wczytaj (consult). fam2.pl: matka(M,D) :- rodzic(M,D), kobieta(M). ojciec(O,D) :- rodzic(O,D), mezczyzna(O). Proszę zdefiniować reguły opisujące: brata, siostrę, dziadka i babcię. Proszę dokładnie sprawdzić ich działanie. Jaki pojawia się problem przy bracie/siostrze? Uwaga na operator: ''\='' Proszę się zastanowić nad własnymi regułami opisującymi relacje w rodzinie. pf2.pl happy(yolanda). listens2Music(mia). listens2Music(yolanda):- happy(yolanda). playsAirGuitar(mia):- listens2Music(mia). playsAirGuitar(yolanda):- listens2Music(yolanda). ===== Wyszukiwanie wszystkich rozwiązań rozwiązań ===== Po niektórych pytaniach można nacisnąć średnik ";"... ===== Bazy danych ===== book(signature_1,title_1,author_1,publisher_1,year_1). book(signature_2,title_2,author_2,publisher_2,year_2). book(signature_3,title_3,author_1,publisher_3,year_3). book(signature_4,title_4,author_4,publisher_4,year_4). book(signature_5,title_5,author_1,publisher_5,year_5). journal(journal_id_1,title_1,volume_1,number_1,year_1). journal(journal_id_2,title_2,volume_2,number_2,year_2). journal(journal_id_3,title_3,volume_3,number_3,year_3). journal(journal_id_4,title_4,volume_4,number_4,year_4). journal(signature_5,title_5,volume_5,number_5,year_5). user(id_1,surname_1,forename_1,born_1,address_1). user(id_2,surname_2,forename_2,born_2,address_2). user(id_3,surname_3,forename_3,born_3,address_3). user(id_4,surname_4,forename_4,born_4,address_4). user(id_5,surname_5,forename_5,born_5,address_5). register(id_1,signature_1,borrow_date_1,return_date_1). register(id_1,signature_2,borrow_date_2,return_date_2). register(id_2,signature_1,borrow_date_3,return_date_3). %%% Algebraic operations sum(Id,Title,Year):- book(Id,Title,_,_,Year); journal(Id,Title,_,_,Year), not(book(Id,Title,_,_,Year)). intersect(Id,Title,Year):- book(Id,Title,_,_,Year), journal(Id,Title,_,_,Year). except(Id,Title,Year):- book(Id,Title,_,_,Year), not(journal(Id,Title,_,_,Year)). projection(Title,Author,Year):- book(_,Title,Author,_,Year). selection(Signature,Title,Author,Publisher,Year):- book(Signature,Title,Author,Publisher,Year), Author = author_1. cartesian_product(Signature,Uid):- book(Signature,_,_,_,_), user(Uid,_,_,_,_). who_what_book(Uid,Surname,Name,Signature,Title,BorrowDate,ReturnDate):- register(Uid,Signature,BorrowDate,ReturnDate), user(Uid,Surname,Name,_,_), book(Signature,Title,_,_,_). Brak I/O % Definicje działania bramek podstawowych not(1,0). not(0,1). and(0,0,0). and(0,1,0). and(1,0,0). and(1,1,1). or(0,0,0). or(0,1,1). or(1,0,1). or(1,1,1). % Definicja przykładowego układu - xor xor(Input1,Input2,Output) :- not(Input1,N1), not(Input2,N2), and(Input1,N2,N3), and(Input2,N1,N4), or(N3,N4,Output). % Przykładowe testy: % xor(1,0,W), xor(1,I,1), xor(I1,I2,0) ===== Zapamiętywanie nowych faktów ===== Predykaty //assert/a/z /1//, //retract/a/z /1// pozwalają na dodawanie, usuwanie faktów do/z bazy wiedzy, na/do jej początku/końca. Predykat //abolish/1// pozwala usunąć predykat z bazy wiedzy. (np. ''abolish(kobieta/1).'') Predykat //retractall/1// pozwala usunąć klauzule danego predykatu z bazy wiedzy. (np. ''retractall(kobieta(K)).'') **Ćwiczenie** Proszę napisać: ?- assert(kobieta(kopernik)). jak zmieniła sie wiedza na temat kobiet? ?- listing(kobieta). Proszę sprawdzić: kobieta(K),write(K),write(' to kobieta.'),nl,fail. Uwaga: niektóre kompilatory Prologu (np. SWI) wymagają wcześniejszego zadeklarowania predykatu jako takiego, który może być dynamicznie modyfikowany. Robi się to przez predykat //dynamic/1//, np. dla predykatu //kobieta/1// deklaracja w pliku //fam2.pl// ma postać '':- dynamic(kobieta/1).''. Proszę oglądnąć zastosowanie //assert/retract// na przykładzie programu {{:pl:prolog:prolog_lab:learner.pl}} Początkowa baza wiedzy jest w pliku {{:pl:prolog:prolog_lab:learner_kb.pl}} Należy uruchomić program przez ''start.'' Jakie 3 przypadki odpowiedzi są brane pod uwagę? Co dzieje się przy wyjściu z programu i jak to wpływa na jego kolejne uruchamianie? Uwaga: operator ''\+'' oznacza //negację//. ===== Dla zaawansowanych ===== liczby-send.pl % Fakty: definicja dostępnych cyfr. cyfra(0). cyfra(1). cyfra(2). cyfra(3). cyfra(4). cyfra(5). cyfra(6). cyfra(7). cyfra(8). cyfra(9). % Skrót nazwy predykatu cyfra/1. c(X) :- cyfra(X). % Rozwiązanie dla problemu SEND + MORE = MONEY solve(S,E,N,D,M,O,R,E,Y) :- c(M),M > 0, c(S),c(E), c(N), c(D), c(M), c(O), c(R), c(Y), S \= E, S \= N, S \= D, S \= M, S \= O, S \= R, S \= Y, E \= N, E \= D, E \= M, E \= O, E \= R, E \= Y, N \= D, N \= M, N \= O, N \= R, N \= Y, D \= M, D \= O, D \= R, D \= Y, M \= O, M \= R, M \= Y, O \= R, O \= Y, R \= Y, L1 is S*1000 + E*100 + N*10 + D, L2 is M*1000 + O*100 + R*10 + E, L3 is M*10000 + O*1000 + N*100 + E*10 + Y, Q is (L1 + L2) - L3, % write(Q),nl, Q = 0. sm : - solve(S,E,N,D,M,O,R,E,Y), write(' '),write(S),write(E),write(N),write(D),nl, write('+'),write(M),write(O),write(R),write(E),nl, write(M),write(O),write(N),write(E),write(Y). Dalsza rozbudowa bazy wiedzy PF, przepisz treść i zadaj pytania podane w [[http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse1|LPN]]. ===== Źródła ===== * [[http://ai.ia.agh.edu.pl/wiki/pl:prolog:prolog_lab|Prolog Lab]] * [[http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlch1|Learn Prolog Now]] * [[http://www.amzi.com/AdventureInProlog|Adventure in Prolog]] * [[http://ai.ia.agh.edu.pl/wiki/pl:prolog:prolog_lab:constraint_satisfaction_problems|Opisywanie problemów za pomocą ograniczeń]]