====== CLIPS ===== Manual do CLIPS dostępny jest na [[http://clipsrules.sourceforge.net/|Stronie projektu]] ===== Wstęp ===== ====Systemy ekspertowe==== Cytując Profesora Edwarda Feigenbauma z Uniwersytetu Stanforda, jednego z pionierów systemów ekspertowych, systemy te można zdefiniować jako: // Inteligentny program komputerowy, który korzysta z wiedzy i procedur wnioskowania do rozwiązania problemu, który jest na tyle trudny, że wymaga do rozwiązania wiedzy eksperckiej. // W szczególności można porównaæ system ekspertowy do procesu podejmowania decyzji przez prawdziwego eksperta. Ekspert to osoba, która posiada bardzo specjalistyczną wiedzę, niedostępną dla większości ludzi. Potrafi on rozwiązać problem, z którym wiêkszość nie mogła by sobie poradziæ, lub potrafi zrobiæ to znacznie efektywniej. ====CLIPS==== System ekspertowy przy pomocy CLIPS można tworzyć na dwa sposoby: * w całości w konsoli (wyjątkowo niewygodne) * w pliku, który następnie wczytywany jest w konsoli przy pomocy polecenie //load//. Ćwiczenie ma na celu stworzenie prostego kalkulatora zdolności kredytowej. **Reguły opisane poniżej są fikcyjne!!** //Przez zdolność kredytową rozumie się zdolność do spłaty zaciągniętego kredytu wraz z odsetkami w terminach określonych w umowie.// ===Tips & Tricks=== * CLIPS odziedziczył częściowo składnie po języku LISP, dlatego wszystkie polecenia muszą być objęte nawiasami okrągłymi * Aby otworzyc konsole CLIPS należy w konsoli Linux wpisać polecenie clips * Aby **wyjść z konsoli** CLIPS należy wpisać polecenie (exit) * Aby **wczytać plik** z regułami/faktami, należy wydać polecenie: (load filename) (reset) Polecenie //(reset)// wczytuje fakty zdefiniowane przy pomocy **deffacts** do bazy faktów. * Aby **wyczyścić bazę** wiedzy i faktów wpisujemy polecenie (clear) * Aby **uruchomić** proces wnioskowanie wpisujemy polecenie (run) * Aby wywołać //helpa// należy wpisać polecenie (help) * **Komentarze** w pliku oznaczane są znakiem ; (średnik). * Przyjęło się, że rozszerzenie pliku z regułami dla CLIPS to **.clp** ==== Fakty ==== - Fakty które powinny znaleźć się w bazie faktów definiowane są przy pomocy polecenia **deffacts**. Na przykład chcąc dodać kilka faktów określających imię, nazwisko i wiek osoby należałoby wpisać w konsoli (lub w pliku) następujące polecenia:(deffacts wejsciowe "komentarz" (imie jan) (nazwisko kowalski) (wiek 24)) Aby fakty zostały dodane do bazy faktów konieczne jest wydanie polecenia //(reset))//. **Uwaga** Fakty w obrębie **deffact** nie są ze sobą w żaden sposób powiązane. W przypadku powyżej, zostana dodane do bazy faktów trzy niezależne fakty: //(imie jan)//, //(nazwisko kowalski)// oraz //(wiek 24)//. - Fakty można dodawać za pomocą polecenia //assert//: (assert (wiek 23)) Fakt taki jest natychmiast dodawany do bazy faktów, jednakże po wywołaniu polecenia //(reset)// w bazie faktów pozostaną tylko fakty dodane przy pomocy polecenia //deffacts//. - fakty mogą sie składać z jedego lub wiecej członu. Wszystkie poniższe fakty są poprawne: (deffacts mojeFakty (rok 2010) (osoba jan kowalski 45) (informatyka)) - Modyfikowanie i usuwanie faktów możliwe jest dzięki poleceniom **retract** oraz **modify** - Aby wyświetlić wszystkie fakty znajdujące się w bazie faktów należy wydać polecenie (facts) ===Cwiczenie=== Przy pomocy polecenia **deffacts** zdefiniuj fakty zawierające dane osobowe: imię, nazwisko, wiek, zarobki. Wczytaj plik z faktami i wyświetl je w konsoli CLIPS. ==== Reguły ==== - Definiowanie reguł możliwe jest dzięki poleceniu **defrule**. Aby dodać regułę, która wypisze komunikat //Hello world// jeśli w bazie faktów znajduje się fakt //imie jan// należy wpisać następującą linijkę:(defrule regula-1 "Komanarz" (name jan) => (printout t "Hello World!" crlf)) - Jeśli w bazi faktów znajduje się kilka faktów rozpoczynających się od //name// możemy chcieć żeby program wyświetlił jeszcze imię osoby do której kierowane jest pozdrowienie. W takim wypadku reguła wygądałaby następująco:(defrule regula-1 "Komanarz" (name ?wartosc) => (printout t "Hello World!" ?wartosc crlf)) - Chcąc sprawdzić czy wartość faktu jest równa, różna, mniejsza, większa od jakiejś zadanej wartości, używamy polecenia //test//. Na przykład chcąc sprawdzić, czy wiek jakiejś osoby jest mniejszy niż 18, należałoby wpisać następującą regułę:(defrule regula-1 "Komentarz" (name ?imie) (wiek ?age) (test (< ?age 18)) => (printout t "Czesc " ?imie ". Nie jestes jeszcze dorosly. Nie powinno Cie byc na PIWie" crlf)) ===Ćwiczenie=== Zdefiniuj dwie reguły, które będą określały, czy osoba może być potencjalnym kredytobiorcą. Jeśli wiek osoby jest mniejszy niż 18 lat, nie może być, jeśli większy i jej zarobki przekraczają 1500zł - można przyznać jej kredyt. Po uruchomieniu wnioskowania powinna zostać wyświetlona informacja "mozna przyznac kredyt" lub "niemozna przyznac kredytu". ==== Templates ==== Fakt może składać się z dowolnej liczby elementów. Oba poniższe fakty są poprawne: (assert (imie szymon)) (assert (osoba o imieniu szymon)) Pierwszy elementem faktu zawsze musi być jednak symbol. Zapis jak powyżej nie nadaje się specjalnie do faktów, które powinny reprezentować jakieś bardziej złożone dane. Do definiowania złożonych faktów używa się polecenia **deftemplate** lub **defclass**. Przykład który definiuje wzorzec o nazwie osoba, zawierający trzy pola: //imie, nazwisko wiek//: (deftemplate osoba (slot imie) (slot nazwisko) (slot wiek)) Do wartości wzorca można odwoływać się z pominięciem niektórych pól:(assert (osoba (imie jan) (nazwisko kowalski) (wiek 50)) (defrule reugla "" (osoba (wiek ?value)) (test (>= 18 ?value)) => (printout t "Hello!" crlf)) ===Ćwiczenie=== Zdefiniuj wzorzec osoba, który będzie przechowywał dane jak w poprzednich ćwiczeniach, zmodyfikuj reguły aby działały z faktami stworzonymi według tego wzorca. ==== Moduły ==== Moduły pełnią w CLIPS kilka funkcji funkcję: - Pomagają zarządzać większymi zbiorami reguł, grupować je - Poprawiają wydajność (dla każdego modułu osobna sieć RETE) - Umożliwiają proste sterowanie wnioskowaniem (polecenie //focus//) ===defmodule=== Moduły definiowane są przy pomocy polecenia **defmodule**: (defmodule MojModul) Przynależność reguł do modułu ustala się podczas definicji reguły stosując operator **::** (semantyka zbliżona do znanego z C++ operatora zasięgu):(defrule MojModul::regula "" => (printout t "---- Regula w module MojModul ----" crlf) ===import oraz export=== Podczas definiowania modułów można określić czy fakty dodawane przez reguły/wzorce/klasy wchodzące w jego skład maja być widoczne w innych modułach. Służy do tego słowo kluczowe **export**:(defmodule mojModul (export ?ALL)) Aby wyeksportowane elementy były widoczne w definiowanym module, należy określić co i z jakiego innego modułu ma on //importować//:(defmodule mojModul (export ?ALL) (defmodule mojInnyModul (import mojModul ?ALL)) Wszystko co nie jest explicite przypisane do żadnego modułu znajduje się w module MAIN. Dobrze jest zatem na początku redefiniować moduł MAIN, tak aby eksportował on wszystko (dzięki temu będzie można to zaimportować w pozostałych modułach).(defmodule MAIN (export ?ALL)) ===focus=== Możliwe jest ustalenie kolejności w jakiej zdefiniowane moduły będą przetwarzane przez silnik wnioskujący. - Możliwe jest arbitralne ustalenie kolejności w jakiej moduły będą przetwarzane:(defrule MAIN::startrule "" => (printout t "---- STARTING ----" crlf) (focus salutation greeting userMessage) ; inference control ) - Możliwe jest przełacznie modułów w prawej części reguły (RHS):(defrule MAIN::reugla "" (osoba (wiek ?value)) (test (>= 18 ?value)) => (printout t "Przełączam moduł z MAIN na adoult" crlf) (focus adoult)) ===Ćwiczenie=== Określ trzy moduły ZdlonoscPrywatna i ZdolnoscFinansowa, ZdolnoscKoncowa. Dodaj pośrednie fakty //zdpriv, zdfin, zdkon// które będą ustalane odpowiednio w module ZdlonoscPrywatna, ZdolnoscFinansowa i ZdolnoscKoncowa. ==Moduł ZdolnoscPrywatna== Zdolności cząstkowe powinny być wyznaczane według poniższej tabeli: wiek, ilość osób w gospodarstwie ^Wiek ^ Ilość osób w gospodarstwie ^ zdpriv ^ | <0 ; 17> |ANY | 0 | | <18 ; 24> |<0; 2> | 3 | | <18 ; 24> |<3 ; 4> | 2| | <18 ; 24> |<4 ; inf> | 0| | <25 ; 65> |<0; 2> | 5| | <25 ; 65> |<3 ; 4> | 3| | <25 ; 65> |<4 ; oo> | 1| | <66 ; 75> |<0; 2> | 4| | <66 ; 75> |<3 ; 4> | 3| | <66 ; 75> |<4 ; inf> | 2| | <75 ; oo> |ANY | 0 | ==Moduł ZdolnoscFinansowa== Zdolność finansowa wyznaczana powinna być według poniższej tabeli: dochód, umowa o prace, inne kredyty. ^Dochód ^ Typ umowy ^ Inne kredyty^ zdfin ^ |<0; 1000>| ANY | ANY | 0| |<1001; 2000> | oprace | nie | 2| |<1001; 2000> | oprace | tak | 1| |<1001; 2000> | inne | ANY | 0| |<2001; 6000> | oprace | nie | 4| |<2001; 6000> | oprace | tak | 2| |<2001; 6000> | inne | ANY | 1| |<6001; 30000> | oprace | nie | 6| |<6001; 30000> | oprace | tak | 4| |<6001; 30000> | inne | ANY | 2| |<30001; oo> | ANY | ANY | 6| ==Moduł ZdolnoscKoncowa== Ostateczna zdolność kredytowa wyliczana jest według następującego wzoru: (zdpriv*2 + zdfin*5)*1000. Moduły powinny być uruchamiane w następującej kolejności (użyj //focus//): - ZdolnoscPrywatna - ZdolnoscFinansowa - ZdolnoscKoncowa ==== Interakcja z użytkownikiem === jedna z możliwych interakcji z użytkownikiem jest pobieranie do niego danych bezpośrednio z klawiatury. Do tego celu służy polecenie **(read)**: defrule regula "" => (printout t "Podaj swoj wiek: ") (bind ?wiek (read)) (printout t "Podaj swoje imie: ") (bind ?imie (read)) (printout t "Podaj swoje nazwisko: ") (bind ?nazwisko (read)) (assert(osoba(imie ?imie)(nazwisko ?nazwisko)(wiek ?wiek)))) Wczytywanie danych od użytkownika może być wykonywane tylko w RHS reguły. ===Ćwiczenie=== Zmodyfikuj program tak, aby możliwe było wczytywanie danych od użytkownika na temat jego sytuacji rodzinnej i finansowej. Po wczytaniu danych powinno zostać uruchomione wnioskowanie i wyświetlona odpowiedź na temat wysokości kredytu jaki dany użytkownik może otrzymać. ===== UWAGI ===== * kilka słów wprowadzenia teoretycznego * więcej przykładów "za rączkę" * w materiałach wykłąd w pdf do pobrania ===== Komentarze ===== Z braku lepszego miejsca tutaj studenci wpisują komentarze natury ogólnej do tego lab. 8-)