Ćwiczenie numer 2 JESS FAKTY, REGUŁY 1. Cel ćwiczenia 1) Celem ćwiczenia jest zapoznanie się z jedną z form reprezentacji wiedzy w JESS, czyli faktami. Rodzaje faktów, oraz sposoby ich implementacji w programie. Szablony do tworzenia faktów. 2) Celem ćwiczenia jest zapoznanie się z jedną z form reprezentacji wiedzy w JESS, czyli regułami. Reguły, oraz sposoby ich implementacji w programie. 2. Opis ćwiczenia Reprezentacja wiedzy w dziedzinie sztucznej inteligencji jest jednym z głównych problemów, które jeszcze nie zostały rozwiązane. Wiedza oznacza zbiór wiadomości z określonej dziedziny, wszelkie zobiektywizowane i utrwalone formy kultury umysłowej i świadomości społecznej powstałe w wyniku kumulowania doświadczeń i uczenia się. Można powiedzieć, że wiedza jest symbolicznym opisem otaczającego nas świata rzeczywistego. JESS pozwala na reprezentowanie wiedzy w postaci faktów. Zbiór takich faktów zwany jest w składni JESS jako pamięć robocza. Cała taka wiedza (zbiór informacji) jest reprezentowana w postaci faktów w pamięci roboczej. Dla przykładu jeżeli nasz program polega na kontroli klimatyzatora, to faktami będą temperatura, wilgotność, i inne. Fakty jak większość konstrukcji w JESS zapisane są w postaci listy. Fakt jest najmniejszą częścią informacji, która może być dodana lub usunięta z pamięci roboczej systemu ekspertowego. Fakty nie są pojedynczymi atomami, mają zazwyczaj określoną strukturę. Na elementach pamięci roboczej jakimi są w fakty można dokonywać różnych operacji. Do podstawowych operacji należą: reset inicjacja pamięci roboczej assert dodanie nowego faktu retract usunięcie faktu facts wyświetlenie zawartości pamięci roboczej (faktów) clear usunięcie wszystkiego z pamięci roboczej
ASSERT: (assert (lista_faktow temperatura wilgotnoscć)) Jako wynik takiego działania zostanie dodany fakt do pamięci roboczej. Aby go wyświetlić posługujemy się poleceniem. RETRACT: (assert (lista_faktow temperatura wilgotnosc)) (assert (lista_faktow2 temperatur2 wilgotnosc2)) (retract 1) Jako wynik takiego działania zostaną utworzone 2 fakty, następnie poleceniem (retract numer_faktu) zostanie usunięty wybrany fakt. Czasami zamiast dodawać fakty poleceniem assert możemy posłużyć się poleceniem deffacts, które pozwala na hurtowe dodawanie faktów. Jest to przydatne kiedy chcemy wprowadzić do pamięci roboczej fakty początkowe, na podstawie których dokona się proces wnioskowania. Konstrukcja taka ma postać: (deffacts catalog "Product catalog" (product 1 sticky-notes "$1.99") (product 2 paper-clips "$0.99") (product 3 blue-pens "$2.99") (product 4 index-cards "$0.99") (product 5 stapler "$5.99")) Dodane zostanie 5 faktów, które poleceniem załadujemy do pamięci roboczej. Fakty takie można później usuwać podobnie jak we wcześniejszym przykładzie, należy podać tylko odpowiedni numer faktu.
W JESS można wyróżnić następujące rodzaje faktów, które różnią się między sobą sposobem ich implementacji: unordered facts (fakty nieuporządkowane) ordered facts (fakty uporządkowane) Fakty nieuporządkowane Ich podstawową charakterystyką jest to, że posiadają określoną strukturę: (deftemplate person (name Jan Kowalski) (age 23 ) (eye-color blue) (hair-color brown)) W JESS można definiować (tworzyć) różne rodzaje faktów nieuporządkowanych. Należy jednak pamiętać, że aby dodać jakiś fakt nieuporządkowany musimy wcześniej zdefiniować jego szablon, co pokazano poniżej: (deftemplate person "People" (slot name) (slot age) (slot gender)) (assert (person (age 34) (name "Bob Smith") (gender Male))) W przypadku, w którym dodając nowy fakt nie podamy wartości slotu, przyjmie on wartość nil (pustą). Np.: nie podajemy slotu name: (assert (person (age 34) (gender Male))) Taki fakt zostanie dodany, a pod wartość name zostanie przypisana wartość pusta. Można także domyślnie każdemu slotowi przypisać konkretną wartość, jeżeli nie podamy wartości slotu podczas dodawania faktu to zostanie pod niego automatycznie przypisana wartość domyślna. Wartość domyślną dodajemy przy definiowaniu szablonu faktu: (deftemplate person "People" (slot name (default "Jan Kowalski")) (slot age) (slot gender))
Można także tworzyć tzw. multisloty. W sytuacji kiedy chcemy lub wiemy, że dana wartość slotu składa się więcej niż z jednego symbolu, np.: wartość slotu to opis (składający się z kilku symboli), należy posłużyć się trochę inna konstrukcją szablonu faktu: (deftemplate person "People" (slot name) (slot age) (multislot hobbies)) Tworząc fakt jako wartość hobbies możemy użyć ciągu symboli, np.: sport, tv, gry etc.. Osoba taka ma kilka wartości slotu hobbies. (assert (person (age 34) (name "Bob Smith") (gender Male) (hobbies sport, tv, gry etc. ) )) Wartości poszczególnych faktów mogą zostać modyfikowane przy pomocy polecenia modify. (deftemplate person "People" (slot name) (slot age) (slot gender)) (assert (person (age 34) (name "Bob Smith") (gender Male))) (modify 1 (age 23)) Zmieniona zostanie wartość age na nową = 23. Fakty uporządkowane Są one prostymi listami, gdzie pierwszym polem jest rodzaj kategorii faktu. Np.: (stal niklowana) (data-godzina 12.12.2011 19:30) (lista-numerow 2 32 3 5 6 7 34 32 4)
W sytuacji, w której dany fakt nie musi mieć wielu slotów lepiej posłużyć się faktami uporządkowanymi. Fakty takie definiujemy w postaci szablonu przed dodaniem faktu z konkretnymi wartościami. (deftemplate number (slot value)) (assert (number (value 123))) Podobnie jak w przypadku z faktami nieuporządkowanymi możemy posługiwać się poleceniami usuwania I modyfikowania takich faktów. Modyfikowanie: (deftemplate number (slot value)) (assert (number (value 123))) (modify 1 (value 1)) Usuwanie: (deftemplate number (slot value)) (assert (number (value 123))) (retract 1) 3. Opis ćwiczenia JESS pozwala na reprezentowanie wiedzy w postaci reguł. Zbiór reguł w JESS to typowa baza wiedzy. Podczas tworzenia systemów ekspertowych najważniejsze i najtrudniejsze jest pozyskanie wiedzy od ekspertów z dziedziny tworzonego systemu. Zdobytą wiedzę należy odpowiednio zapisać w naszym systemie w postaci zbioru reguł. Program posiadający zestaw faktów i reguł, oraz interfejs współpracy z użytkownikiem, który dokonuje procesu wnioskowania na zestawach tych danych można nazwać systemem ekspertowym. JESS posiada dwa mechanizmy wnioskowania:
Wnioskowanie wprzód Wnioskowanie wstecz Na regułach podobnie jak na faktach można dokonywać różnych operacji. Do podstawowych operacji należą: defrule definiowanie nowej reguły undefrule usunięcie reguły run uruchomienie odpalania reguł, czyli proces wnioskowania DEFRULE: (defrule nazwa_reguly "regula nic nie robi" ) Jako wynik takiego działania zostanie wyświetlone tylko TRUE. Jest to tylko przykład reguły, która nie robi nic. Postać każdej reguły jest następujący: IF THEN, czyli jeżeli coś jest prawdziwe to wykonaj działanie. W JESS słówko THEN to znak, aby działanie po prawej stronie znaku wykonało się wszystko co znajduje się po jego lewej stronie musi być prawdziwe. Gdy mamy już tak utworzoną regułę możemy wpisać do konsoli poniższe komendy: (watch facts) (watch activations) (watch rules) (run) Watch facts, activations i rules to funkcje, które w konsoli wyświetlą nam odpowiednie informacje. Reset ładuje fakty do pamięci roboczej (kiedy użytkownik sam nie wprowadzi faktu, w JESS zawsze istnieje fakt początkowy initial, który jest przez niego używany). Run odpowiada za odpalenie reguł. Polega to na tym, że przegląda on bazę reguł i fakty, jeżeli reguła może zostać uruchomiona przez fakt to jest ona uruchamiana. Jest to typowy proces wnioskowania, który JESS wykonuje samodzielnie. UNDEFRULE: (undefrule nazwa_reguly) Polecenie to usunie nam daną regułę.
Poniżej przedstawiam kompletny fragment kodu JESS, w którym mamy funkcję, regułę i fakt: (watch all) (deffunction change-baby () (printout t "Baby is now dry" crlf)) (defrule change-baby-if-wet "If baby is wet, change its diaper."?wet <- (baby-is-wet) (change-baby) (retract?wet)) (assert (baby-is-wet)) (run) Aby reguła została odpalona musi być fakt uruchamiający tą regułę. Dodaliśmy fakt poleceniem assert. Run uruchomi proces wnioskowania, sprawdzi, że jest jedna reguła, którą można aktywować i to robi. Reguła jako efekt działania uruchamia naszą funkcję, która wyświetla nam informację. (defrule literal-values (letters b c) ) (watch activations) (assert (letters b d)) (assert (letters b c)) W tym przypadku dodajemy dwa fakty, pierwszy z nich nie uruchomi naszej reguły. Dodaje on litery b i d, aby uruchomić regułę potrzeba liter b i c, litery te dodaje fakt drugi, który uruchomi naszą regułę. (defrule repeated-variables (a?x) (b?x) (printout t "?x is "?x crlf)) (watch activations) (deffacts repeated-variable-facts (a 1) (a 2) (b 2) (b 3)) (run)
Mamy tutaj regułę, która zostanie aktywowana tylko wtedy, gdy fakty będą się powtarzać. Dodajemy jako fakty 4 liczby, powtarza się liczba z faktu 2 i 3, dlatego to te fakty uruchomią naszą regułę. Przedstawione teraz będą reguły, których przesłanki są bardziej rozbudowane. Przesłanki muszą być prawdziwe, aby reguła została uruchomiona. Jako efekt pracy reguły może zostać wyświetlona informacja, dodany/usunięty/zmodyfikowany fakt, lub nawet wywołanie funkcji. (deftemplate person (slot age)) (defrule find-trustworthy-people-1 (person (age?x)) (test (<?x 30)) (printout t?x " is under 30!" crlf)) W tym przypadku reguła wymaga aby osoba miała wiek poniżej 30 lat. Tylko dla takiej osoby reguła zadziała. (deftemplate used-car (slot price) (slot mileage)) (deftemplate new-car (slot price) (slot warrantyperiod)) (defrule might-buy-car?candidate <- (or (used-car (mileage?m&:(<?m 50000))) (new-car (price?p&:(<?p 20000)))) (assert (candidate?candidate))) (assert (new-car (price 18000))) (assert (used-car (mileage 30000))) (run) Tutaj reguł sprawdza nam informacje o samochodach, jeżeli używany samochód ma mniej niż 50k km na liczniku lub nowy ma cenę poniżej 20k zł to samochody takie są polecane użytkownikowi. Aby taka reguła została uruchomiona wystarczy jeden fakt, który ją spełnia (mamy słówko or, and powoduje, że obydwa fakty musiałby być spełnione).
4. Zadania Kod przydatny do zapętlenia programu, aby pytał czy chcemy kontynuować znajduje się poniżej: (bind?co 1) (while (=?co 1) do (kod naszego programu) (printout t "Dodac nowego" crlf) (printout t "tak / nie" crlf) (bind?odp (read)) (if (=?odp tak) then (bind?co 1) else (bind?co 0) ) ) Mgr inż. Marynowski Przemysław pmarynow@agh.edu.pl