Programowanie w
JESS
mgr inż. Marynowski Przemysław
pmarynow@agh.edu.pl
, A2-53H.
Podstawy tworzenia systemów ekspertowych.
1
JESS
jest to system ekspertowy opracowany w języku Sun Java przez Ernest Friedman-
Hillat Sandia National Laboratories.
Pierwsza wersja
JESS
została stworzona w 1995 roku i rozwija się nieustannie.
Programowanie w tym języku również może być wsparte językiem Java.
Używany może być zarówno pod Windowsem, a także pod UNIXem. Kompatybilny
jest z wszystkimi wersjami Java.
JESS
można wykorzystać do programowania systemów ekspertowych, których
zadaniem jest wierne naśladowanie ludzkiego eksperta.
JESS
– może również spełnić role języka ogólnego programowania. Przy wykorzystaniu
bibliotek Java może mieć bardzo szerokie zastosowanie.
JEES - pojęcie
2
System ekspertowy
- jest to program lub zestaw programów komputerowych
wspomagający korzystanie z wiedzy i ułatwiający podejmowanie decyzji. Systemy
ekspertowe mogą wspomagać bądź zastępować ludzkich ekspertów w danej dziedzinie,
mogą dostarczać rad, zaleceń i diagnoz dotyczących problemów tej dziedziny – co
zostało przedstawione na pierwszym wykładzie.
System ekspertowy - pojęcie
3
1.Explanation facility
– wyjaśnia proces wnioskowania, który doprowadził do danej
konkluzji.
2.Knowledge
acquisition
facility
–
dostarcza
sposobów
do
pozyskania
i
przechowywania wiedzy pozyskanej od eksperta w bazie wiedzy (
knowledge base
).
3.Knowledge base
- przechowuje wiedzę w postaci reguł.
4.Working memory
- baza faktów wykorzystywanych przez reguły.
5.Inference engine
- decyduje które reguły, i w jakiej kolejności zostaną
uruchomione.
6.Agenda
- lista reguł, których warunki spełnione są przez fakty znajdujące się w
pamięci roboczej (
working memory
)
7.Pattern matcher
- porównuje reguły i fakty.
Z czego składa się system ekspertowy ?
4
System ekspertowy
5
Fakt
: „Stal jest stopem żelaza i węgla“
Reguła
: „Jeśli w stali jest domieszka niklu to hartowanie jest ułatwione“
Fakt
: „Adam jest studentem metalurgii“
Reguła
: „Jeśli student jest studentem metalurgii to wie co to jest
hartowanie“
Fakty i reguły
6
Programowanie w JESS – fakty i reguły
Fakt:
(assert (stal (stop zelazo-wegiel ))
Reguła:
(defrule regula1
(stal {domieszka-niklu})
=>
(printout file " Hartowanie jest ułatwione " crlf))
7
Programowanie w JESS – fakty i reguły
Fakt:
(assert (student (Adam metalurgia))
Reguła:
(defrule regula1
(student {metalurgia})
=>
(printout file " Jeśli student jest studentem metalurgii to wie co
to jest hartowanie " crlf))
8
Programowanie w JESS – fakty i reguły
Fakt:
(assert (mechanizm (mech pekanie))
Reguła:
(defrule regula1
(stal {gatunek == ST5})
=>
(printout file "Gatunek stali to ST5" crlf))
9
Fakty
:
- niemodyfikowalne (modyfikacja faktu oznacza jego usunięcie i stworzenie
nowego)
- mogą być tworzone
- mogą byś usuwane
Reguły
:
- składają się z „poprzedników“ i „następstw“
- reguła zostaje uruchomiona gdy spełniony jest poprzednik/poprzednicy
- następstwem reguły jest najczęściej modyfikacja lub dodanie nowych faktów
do pamięci roboczej (
working memory
)
Programowanie w JESS – fakty i reguły
10
Programowanie w JESS – fakty i reguły
Produkcja faktów:
Fakty uruchamiają reguły, które produkują nowe fakty, które uruchamiają reguły,
które... itd. itd.
Program kończy się gdy nie ma już reguł, które można by uruchomić. Wynikiem
działania programu jest lista faktów w pamięci roboczej.
Wiedza reprezentowana jest przez:
-
unordered facts
(fakty nieuporządkowane)
-
ordered facts
(fakty uporządkowane)
-
rules
(reguły)
11
Fakty uporządkowane
Są one prostymi listami, gdzie pierwszym polem jest rodzaj kategorii faktu.
(jan kowalski)
(pogoda słoneczna)
(stal niklowana)
(data-godzina 12.12.2011 19:30)
(lista-numerow 2 32 3 5 6 7 34 32 4)
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))
Programowanie w JESS – fakty
12
W przypadku faktów uporządkowanych by odnieść się do
danego pola/symbolu należy znać jego pozycję.
W przypadku faktów nieuporządkowanych używa się nazwy
slotu.
Programowanie w JESS – fakty
13
Fakty nieuporządkowane (unordered facts):
Struktura (definicja faktu):
Typ faktu: person
(deftemplate person "An example deftemplate"
(slot name)
(slot age)
(slot eye-color)
(slot hair-color))
Programowanie w JESS – fakty
14
Fakty nieuporządkowane (unordered facts):
Tworzenie (dodawanie) faktów:
(assert (person (name John Q. Public)
(age 23 )
(eye-color blue)
(hair-color brown)))
Programowanie w JESS – fakty
15
(deftemplate question
(slot factor (default none))
(slot question-to-ask (default none))
(slot has-pre-condition (type SYMBOL) (default no))
(multislot choices (default yes no))
(multislot range (type INTEGER)))
Słowa kluczowe:
- deftemplate: definicja faktu
- slot: pojedynczy symbol
- multislot: wiele symboli
- type: typ symbolu
- default: wartość domyślna
Programowanie w JESS – fakty
16
Dodawanie faktów:
(assert <fakt>)
Usuwanie faktów:
(retract <indeks-faktu>)
Wyświetlenie faktów:
(facts)
Załadowanie faktów do pamięci roboczej JESS:
(reset)
Usunięcie faktów oraz reguł!:
(clear)
Programowanie w JESS – fakty
17
„Hurtowe“ dodawanie faktów danego typu (unordered facts):
(deffacts people "Znajomi"
(person (name "Adam Kowalski") (age 24)
(eye-color blue) (hair-color black))
(person (name "Jan Kowalski") (age 24)
(eye-color blue) (hair-color black))
(person (name "Katarzyna Nowak") (age 36)
(eye-color green) (hair-color red)))
Przydatne, gdy chcemy na początku programu dodać zbiór faktów, których wiemy, że
są prawdziwe (tzw. Initial knowledge)
Programowanie w JESS – fakty
18
Programowanie w JESS – reguły
Składnia:
(defrule nazwa
Left-Hand-Side (LHS) (antecedent/poprzednik)
=>
Right-Hand-Side (RHS) (consequent/konsekwencja)
)
LHS – musi być spełnione (true), by reguła została umieszczona na agendzie.
RHS – określa czynności wykonywane przez regułę.
19
IF
alarm pożarowy
THEN
podejmij-akcje uaktywnij zraszacze
Uwaga: przed zdefiniowaniem reguły wszystkie używane przez nią fakty
nieuporządkowane (deftemplate) muszą być zdefiniowane.
(deftemplate alarm (slot typ))
(deftemplate wykonaj-akcje (slot akcja))
(defrule akcja-p.pożarowa “Przykład reguły"
(alarm (typ pożarowy))
=>
(assert (podejmij-akcje (akcja uaktywnij-zraszacze))))
Programowanie w JESS – reguły
20
(defrule akcja-p.pożarowa “Przykład reguły"
(alarm (typ pożarowy))
=>
(assert (wykonaj-akcje (akcja uaktywnij-zraszacze)))
)
Czy tak stworzona reguła zostanie umieszczona na agendzie (wykonana)? Nie.
Stanie się to dopiero, gdy dodamy fakt:
(assert alarm (typ pożarowy))
Rezultat wykonania reguły? Dodanie (produkcja) nowego faktu:
(wykonaj-akcje (akcja uaktywnij-zraszacze))
Programowanie w JESS – reguły
21
Składnia LHS:
(defrule nazwa
(
and
(warunek 1)
(warunek 2) …
)
=>
…
(defrule nazwa
(
or
(warunek 1)
(warunek 2) …
)
=>
...
Programowanie w JESS – reguły
22
Programowanie w JESS – reguły
Składnia RHS:
(defrule nazwa
...
=>
(tworzenie/usuwanie faktu; wypisanie; ..)
(tworzenie/usuwanie faktu; wypisanie; ..)
...
23
Ciąg zdarzeń:
(defrule akcja-p.pożarowa “Przykład reguły"
(alarm (typ pożarowy))
=>
(assert (wykonaj-akcje (akcja uaktywnij-zraszacze)))
)
(defrule uruchamianie-zraszaczy
(wykonaj-akcje (akcja uaktywnij-zraszacze)
(prąd wyłączony)
=>
(assert (uruchom dopływ wody))
(assert (odblokuj zraszacze))
Programowanie w JESS – reguły
24
Programowanie w JESS – reguły
Zmienne reguł i zakresy:
(defrule start-up
(osoba (wiek ?a&:(> ?a 30)&:(< ?a 40)) (imie $?n) )
=>
(printout t "Witaj " ?n ". Masz" ?a "lat" crlf))
Zmienne:
?a – jeden slot, ?n – wiele slotów (multislot), bo zdefiniowana jako $?n (pole imie w
deftemplate osoba jest multislot – może mieć wiele symboli)
Zakres:
?a&:(> ?a 30)&:(< ?a 40) – zmienna ?a, taka że ?a > 30 oraz ?a < 40
25
Programowanie w JESS – reguły
(defrule start-up
(osoba (wiek ?a&:(> ?a 30)&:(< ?a 40)) (imie $?n) )
=>
(printout t "Witaj " ?n ". Masz" ?a "lat" crlf))
Reguła nie zadziała:
(assert (osoba (wiek 22) (imie Jan Kowalski))
Reguła zadziała:
(assert (osoba (wiek 34) (imie Jan Kowalski))
26
Programowanie w JESS – wiedza początkowa
Reguły oraz fakty początkowe – dodane na początku programu za pomocą
deffacts.
(deffacts people "Znajomi"
(person (name "Adam Kowalski") (age 24)
(eye-color blue) (hair-color black))
(person (name "Jan Kowalski") (age 24)
(eye-color blue) (hair-color black))
(person (name "Katarzyna Nowak") (age 36)
(eye-color green) (hair-color red)))
27
Polecenia: bind (załadowanie do zmiennej), read (odczyt jednego pola)
(defrule regula1
(initial-fact)
=>
(printout t „Jak masz na imie?“)
(bind ?imie (read))
(assert (imie ?imie))
?imie – zmienna lokalna reguły
Programowanie w JESS – odczyt z terminala
28
(defrule regula1
(initial-fact)
=>
(printout t „Jak masz na imie?“)
(bind ?imie (read))
(assert (imie ?imie))
(defrule regula2
(imie ?imie)
=>
(printout t „Witaj, “ ?imie „!“ crlf crlf)
(printout t „Wybierz opcje: (a/b/c)“ crlf)
(printout t „ a)“ crlf)
(printout t „ b)“ crlf)
(printout t „ c)“ crlf)
(bind ?odp (read))
(assert (odp ?odp))
)
Programowanie w JESS – odczyt z terminala
29
(defrule regula_a
(odp a)
=>
(printout t „Wybrales odpowiedz a“ crlf))
(defrule regula_b
(odp b)
=>
(printout t „Wybrales odpowiedz b“ crlf))
(defrule regula_c
(odp c)
=>
(printout t „Wybrales odpowiedz c“ crlf))
Programowanie w JESS – odczyt z terminala
30
W JESS można stosować różne operacje matematyczne:
+, -, *, / :
np.
(+ ?x ?y ?z) :
?x + ?y + ?z
(- ?x ?y ?z) :
?x - ?y - ?z
(+ (- ?x ?y) (* ?x 2)) :
(?x - ?y) + (?x * 2)
(- (+ ?x (* ?y ?z)) (/ ?x ?z)) :
(?x + ?y * ?z) - ?x / ?z
Programowanie w JESS – operacje matematyczne
31
(defrule start
(initial-fact)
=>
(printout t „Program oblicza pierwiastki r. kwadratowego: “ crlf)
(printout t „Podaj a : “) (bind ?a (read))
(printout t „Podaj b : “) (bind ?b (read))
(printout t „Podaj c : “) (bind ?c (read))
(assert (a ?a) (b ?b) (c ?c)))
(defrule licz-delte
(a ?a) (b ?b) (c ?c)
=>
(bind ?delta (- (* ?b ?b) (* 4 ?a ?c)))
(assert (delta ?delta)))
Programowanie w JESS – operacje matematyczne
32
(defrule licz-pierwiastki_delta_zero
(delta ?delta) (a ?a) (b ?b)
(
test
(= ?delta 0))
=>
(bind ?x1 (/ (- 0 ?b) (* 2 ?a)))
(bind ?x2 ?x1)
(assert (x1 ?x1) (x2 ?x2)))
(defrule licz-pierwiastki_deltawiekszaodzera … itd.
(defrule pisz-wynik
(x1 ?x1) (x2 ?x2)
=>
(printout t „X1 = “ ?x1 „,X2 = “ ?x2 crlf))
Programowanie w JESS – operacje matematyczne
33
(test (funkcja_porównująca argumenty)) - porównuje liczby, łańcuchy, zmienne.
Zawsze po lewej stronie reguły (LHS)!
Reguła, która ma po lewej stronie funkcję (test ...), zostanie uaktywniona tylko,
gdy będzie spełniony warunek w tej funkcji (oraz inne fakty w LHS).
Funkcje porównujące:
=, <>, >=, >, <=, <
Można używać funkcji logicznych (and, or …)
Np.
(test (> ?delta 0))
(test (<> wynik -1))
Programowanie w JESS – funkcja test
34
Składnia:
(deffunction nazwa_funkcji
(?arg1 ?arg2 … ?argN)
(akcja1)
(akcja2)
…
(akcjaM)) ;
TYLKO OSTATNIA AKCJA ZWRACA WARTOŚĆ!
Programowanie w JESS – funkcje definiowane przez użytkownika
35
(deffunction ostatnia-akcja
(?a ?b) ;argumenty
(printout t „Wartości wejściowe: “ ?a „ “ ?b crlf)
(+ ?a ?b)
(- ?a ?b)
(* ?a ?b))
JESS> (ostatnia-akcja 4 2)
Wartości wejściowe: 4 2
JESS>> 8
Programowanie w JESS – funkcje definiowane przez użytkownika
36
(deffunction pole_romb (?x ?y)
(bind ?pole (/ (* ?x ?y) 2))
(printout t "Pole wynosi " ?pole crlf))
JESS>> (pole_rombu 2 3)
Funkcja odpowiada za obliczenie pola rombu.
Do funkcji przesyłane są 2 parametry – długości przekątnych.
Funkcja w ciele ma napisaną formułę obliczającą pole i zwracającą wynik.
Wywołujemy funkcję z parametrami i otrzymujemy odpowiedni wynik.
Programowanie w JESS – funkcje definiowane przez użytkownika
37
(deffunction dodawanie (?x ?y)
(bind ?suma (+ ?x ?y))
(printout t "suma wynosi " ?suma crlf))
JESS>> (dodawanie 2 3)
Funkcja dodająca dwie liczby do siebie.
Liczby 2 i 3 są to parametry przesłane do funkcji, która wykona na
nich dodawanie.
Jako parametry można przesłać zdefiniowane wcześniej zmienne
lokalne np.: ?a, ?b, gdzie ?a i ?b zostały utworzone poleceniem
(bind) i przypisano im konkretne wartości.
Programowanie w JESS – funkcje definiowane przez użytkownika
38
Wszystkie zmienne, których do tej pory używaliśmy były zmiennymi
lokalnymi poszczególnych reguł.
Zmienna lokalna jest znana tylko w regule, w której jest zdefiniowana.
Zmienne globalne mają zakres całego programu – są znane we
wszystkich regułach.
Uwaga!: Wszędzie tam gdzie to możliwe należy używać faktów, a nie
zmienny globalnych!
Programowanie w JESS – zmienne globalne
39
Definicja:
(defglobal
?*zmienna1* = wartość1
?*zmienna2* = wartość2
…
)
Programowanie w JESS – zmienne globalne
40
np.
JESS> (defglobal ?*a* = 1)
JESS> ?*a*
1
JESS> (bind ?*a* 5)
JESS> ?*a*
5
JESS> (reset)
JESS> ?*a*
1
Programowanie w JESS – zmienne globalne
41
Użycie w regułach:
ŹLE!:
(defrule zla-regula
(y ?*x*)
=>
…)
OK:
(defrule regula-ok
(y ?y)
(test (= ?y ?*x*)
=>
...)
Programowanie w JESS – zmienne globalne
42
43
Programowanie w JESS – pętle
W programowaniu pętla to jedna z trzech podstawowych konstrukcji
programowania strukturalnego (obok instrukcji warunkowej i instrukcji
wyboru).
Umożliwia cykliczne wykonywanie ciągu instrukcji określoną liczbę razy,
do momentu zajścia pewnych warunków, dla każdego elementu listy lub
w nieskończoność.
W JESS istnieje możliwość zastosowania następujących pętli:
•
foreach
•
while
•
if / then/ else
44
Programowanie w JESS – pętle
FOREACH:
Pętla foreach, pętla "po kolekcji", to w programowaniu rodzaj pętli, której
wykonanie polega na powtarzaniu kolejnych iteracji dla wszystkich elementów
wybranych danych, takich jak, np. tablica, lista.
Pętla ta jest przydatna w sytuacji kiedy mamy już listę zmiennych.
Ma ona postać:
(foreach <zmienna> <lista> <wyrażenie>+)
JESS>> (bind ?lista (create$ imie nazwisko adres))
JESS>> (foreach ?e ?lista (printout t ?e crlf))
Wypisane zostaną wszystkie elementy z listy.
45
Programowanie w JESS – pętle
WHILE:
Wykonuje instrukcję tak długo, dopóki jej warunek jest spełniony (ma wartość
prawdziwą).
Instrukcja sprawdza warunek przed wykonaniem ciała pętli.
Pętla while może wykonywać się nieskończoną ilość razy, gdy wyrażenie nigdy nie
przyjmie wartości 0 (fałsz), może także nie wykonać się nigdy, gdy wartość przed
pierwszym przebiegiem będzie FALSE.
Ma ona postać:
(while <wartość logiczna (true / false> do <wyrażenie>+)
JESS>> (bind ?i 1)
JESS>> (bind ?sum 0)
JESS>> (while (<= ?i 10) do
(bind ?sum (+ ?sum ?i))
(bind ?i (+i ?i 1)))
JESS>> ?sum
46
Programowanie w JESS – pętle
IF/THEN/ELSE:
Pętla ta pozwala na wybór, który fragment kodu ma się wykonać.
Instrukcja if (ang. jeśli) to podstawowa instrukcja warunkowa.
Gdy spełniony jest jej warunek - wykonany zostanie kod zawarty po słowie then.
Fragment else jest opcjonalny.
Ma ona postać:
(if <wartość logiczna> then <wyrażenie>+ [else <wyrażenie>+])
JESS>> (bind ?lista (create$ imie nazwisko Krakow))
JESS>> (if (member$ Krakow ?lista) then
(printout t “Ten ktoś mieszka w Krakowie“ crlf)
else
(printout t “Ten ktoś mieszka poza Krakowem“ crlf))
Jeżeli w liście podamy Kraków to zostanie wykonane polecenie po słowie then, jeżeli
podamy inne niż Kraków to wykonany zostanie kod po słowie else.
47