J E S S

Martin Kužela
René Kuzica
Miloslav Krchniak

Znalostný systém napísaný v jazyku Java

Katedra informatiky a výpočtovej techniky,
Fakulta elektrotechniky a informatiky,
Slovenská technická univerzita, Bratislava

OBSAH:

1. Úvod
2. Jazykové konštrukcie Jessu a ich použitie
3. Ako pracuje Jess
4. Prepojenie Jessu s Javou
5. Záver
6. Bibliografia

Abstrakt:

V tomto príspevku prezentujeme znalostný systém Jess.
Jess sa zaraďuje do kategórie shellov, čo znamená, že netvorí samostatný expertný systém, ale poskytuje prostriedky na naprogramovanie expertného systému.

Tento systém nás zaujal svojou jednoduchosťou a tým, že je celý napísaný v jazyku Java, ktorý v súčasnosti patrí medzi najmodernejšie. Ďalšou neopomenuteľnou výhodou je fakt, že je voľne dostupný včítane zdrojového textu.

Referát je po logickej stránke rozdelený do troch častí.
Prvá časť je zameraná na úvod do problematiky a popis základných charakteristík Jessu (Martin Kužela), druhá časť sa zaoberá opisom použitého Rete algoritmu (René Kuzica) a tretia je zameraná na prepojenie systému Jess s programovacím jazykom Java (Miloslav Krchniak).

Keďže pomocou tohto systému vypracovávame aj naše zadanie zo Znalostných Systémov, v referáte sme mali snahu ozrejmiť niektoré veci aj pomocou príkladov z vlastného expertného systému.

Abstract:

In this article we discuss java expert shell Jess.
We are interested in this shell because of it's simplicity and fact, that is entirely written in Java language, which is state-of-the-art. Other advantage of Jess is that is available free including sources.
Article is divided into three parts. First is focused as an introduction and description of basic attributes of Jess. Second is focused into description of Rete algorithm and third to interconnection between Jess and Java.

Kľúčové slová:

Jess, Java, expertný systém, znalostný systém, rámec, slot, Rete algoritmus.

1. Úvod

Predchodcom Jessu bol systém CLIPS. Použitý jazyk obidvoch systémov je prakticky rovnaký. Hlavné rozdiely spočívajú v tom, že CLIPS je napísaný v jazyku C a existuje k nemu množstvo rozšírení, ktoré Jess nepodporuje. Naopak, Jess je oproti CLIPSu silne rozšírený o prepojenie s programovacím jazykom Java, čím získal vlasnosti ako platformová nezávislosť a jednoduchší objektovo-orientovaný kód.
Program napísaný v jazyku CLIPS a aj Jess-e sa silne podobá na program napísaný v jazyku LISP. Jess prevzal z LISPu atómy, zoznamy, funkcie a spôsob zápisu pomocou okrúhlich zátvoriek.

Autor Jessu je Ernest J. Friedman-Hill, pracujúci pre Sandia National Laboratories.
Po skompilovaní sa Jess tvári ako skupina tried (súbory .class), združených do balíka jess. Na skompilovanie a spustenie Jessu treba mať nainštalovaný niektorý z kompilátorov a interpreterov Javy (najčastejšie JDK od firmy Sun).
Jess sa spustí po napísaní do príkazového riadku:

 java jess.Main program.clp 
Program.clp je vlastný program napísaný v jazyku Jess.

2. Jazykové konštrukcie Jessu a ich použitie.

2.1 Pravidlá

Jess používa priame odvodzovanie (dopredný systém riadený údajmi). Používa pritom rámce, ale len ako štruktúrované úložiská údajov - faktov. Nemá teda žiadne metódy, ktoré by sa spúšťali pri práci s rámcami, ale používa univerzálne pravidlá, ktoré sa skladajú z podmienkovej a dôsledkovej časti.

Metóda rámca sa nahradí tak, že v podmienkovej časti pravidla sa nainštanciujú existujúce fakty alebo rámce. Ďalej sa už s nimi v dôsledkovej časti môžu vykonať akcie.
Príklad pravidla, ktoré zistí a uloží nový fakt o zhode dvoch počítačových komponetov. (Pravidlá sa definujú pomocou rezervovaného slova defrule):

(defrule fit-motherboard-case
    ?d <- (motherboard (type ?X))
    ?s <- (case (type ?X))
    =>
    (assert (vyhovuje ?d ?s))
)
Ako vidieť, premenné ?X, ktoré sa nainštancujú, sa musia zhodovať.
V tomto príklade vidieť, že ak Jess nájde dva rámce-fakty, ktoré spĺňajú túto podmienku, dá do premenných ?d a ?s identifikačné čísla týchto rámcov a vykoná dôsledkovú časť, ktorá uloží nový fakt (vyhovuje id1 id2) do bázy faktov.

Klasický problém, keď je potrebné vykonať pri štarte niektoré operácie, sa v Jesse rieši takto:

(deffacts st
  (command "start"))

(defrule initialize
   ?fact <- (command "start")
   =>
   (retract ?fact)
   (printout t "Nahravam" crlf)
   (load-facts "komponenty.dat")
   (printout t "Fakty nahrane" crlf)
)

2.2 Fakty

Ako sme už naznačili, Jess má bázu faktov, ktorá je reprezentovaná súborom zoznamov. Tie môžu byť jednoduché (obyčajné fakty), alebo zložené (vtedy sú to vlastne inštancie rámcov). Fakty sa ukladajú do bázy znalostí buď na začiatku pomocou deffacts, alebo neskôr, pomocou funkcie assert.

Príklad jednoduchého faktu:

(deffacts vyhovuje-fakt
  (vyhovuje pentium doska_pre_pentium)
)
Príklad inštancie rámca:
(deffacts instancia-ramca
  (case (name noname1) (size MIDITOWER) (type ATX))
)

2.3 Rámce

Rámce sa definujú pred vlastným použitím pomocou rezervovaného slova deftemplate. Rámec case použitý v predchádzjúcom príklade bol definovaný nasledovne:
(deftemplate case
   (slot name)
   (slot size)     ; DESKTOP SLIMLINE MIDITOWER BIGTOWER
   (slot type)     ; AT alebo ATX
)

2.4 Premenné

Premenné sa odlišujú od atómov tým, že začínajú otáznikom ? alebo $?. Podľa toho, či sa použije ? alebo $?, sa určí, či premenná môže nadobúdať ako hodnotu atóm (?) alebo zoznam ($?). Priradenie hodnoty do premennej sa deje buď počas inštanciovania v podmienkovej časti pravidla, alebo pomocou funkcie bind.

Príklad na priradenie do premennej pomocou funkcie bind:

(bind ?x "retazec")

(bind $?y ($create prvok1 prvok2 prvok3))
V Jesse existujú aj globálne premenné, ktoré sa definujú pomocou defglobal:
(defglobal $variable = "pociatocna hodnota")

2.5 Funkcie

Funkcie realizujú procedurálnu zložku Jessu. Vlastné funkcie si programátor definuje pomocou deffunction.

Príklad funkcie, ktorá vráti FALSE, ak sa prvok v zozname nenachádza, inak vráti zoznam bez tohto prvku.

(deffunction give_memory_to_motherboard (?pamat $?volne)
  (bind ?idx (member$ ?pamat $?volne))
  if (neq ?idx FALSE)
    then (return FALSE)
    else (return (delete$ $?volne ?idx ?idx))
)
Jess poskytuje množinu základných funkcií na prácu so zoznamami (create$, first$, rest$, member$, delete$,...), faktami (assert, retract) a všetky základné aritmetické (*, +, -, /) a logické ( >, <, =) operácie.
Okrem toho, ako uvidíme, dokáže Jess používať funkcie jazyka Java.

3. Ako pracuje Jess

3.1 Jess ako pravidlový expertný systém


Jess je pravidlový expertný systém. Cieľom Jessu je plynulé aplikovanie množiny "ak - tak" pravidiel na množinu dát (báza faktov). Definujeme pravidlá, ktoré zdokonalia vlastný konkrétny expertný systém. Pravidlá Jessu vyzerajú následovne:
  (defrule library-rule-1
    (book (name ?X) (status late) (borrower ?Y))
    (borrower (name ?Y) (address ?Z))
   =>
    (send-late-notice ?X ?Y ?Z))
Táto syntax je identická so syntaxou používanou v CLIPSe. Toto pravidlo môže byť preložené do pseudokódu nasledovným spôsobom:
   Library rule #1:
   If
     a late book exists, with name X, borrowed by someone named Y
   and
     that borrower's address is known to be Z
   then
     send a late notice to Y at Z about the book X.
Entity book a borrower by sa mali nachádzať v báze faktov. Báza faktov je teda druh databázy častí reálnych vedomostí o svete.
Atribúty entít (SLOTS) smú byť definované vo vyhláseniach nazývaných DEFTEMPLATES. Akcie podobné send-late-notice môžu byť definované v používateľom napísaných funkciách v jazyku Jess (DEFFUNCTIONS) alebo v Jave (USERFUNCTIONS).

Typický expertný systém má pevnú množinu pravidiel, zatiaľ čo báza faktov sa mení nepretržite. Avšak vo väčšine expertných systémov sa veľká časť bázy faktov z jednej pravidlovej operácie do nasledujúcej tiež nezmení. Hoci nové fakty prichádzajú a staré sú odstraňované, percento faktov, ktoré sa zmenili za jednotku času, je všeobecne dosť malé. Z toho dôvodu je zrejmá implementácia expertného systému veľmi nevýkonná.

Táto zrejmá implementácia by mala udržiavať bázu pravidiel a nepretržite cyklicky v báze overovať každú jednu ľavú stranu LHS s bázou faktov a vykonávať pravú stranu RHS akýchkoľvek pravidiel, ktoré by sa uplatnili. To je ale nevýkonné, pretože väčšina testov vykonaných v každom cykle bude mať rovnaké výsledky ako v predchádzajúcej iterácii. Hoci báza faktov je stabilná, väčšina testov bude opakovaná.
Výpočtovú zložitosť takého systému vyjarduje funkcia O(RF^P), kde R je počet pravidiel, P je priemerný počet vzoriek na LHS pravidla a F je počet faktov v báze faktov.

3.2 Výpočtová zložitosť expertných systémov


Jess namiesto toho používa veľmi účinnú metódu známu ako RETE (latinsky sieť) algoritmus. Klasické dielo o RETE algoritme ("RETE: A Fast Algorithm for the Many Pattern/ Many Object Pattern Match Problem", Charles L. Forgy, Artificial Intelligence 19 (1982), 17-37) 17-37) sa stalo základom pre celú generáciu rýchlych expertných systémov: OPS5, jeho potomka ART a CLIPS.

Neefektívnosť popísaná vyššie je v RETE algoritme zmiernená pamätaním si predchádzajúcich výsledkov testov v priebehu iterácie pravidlovej slučky. Iba nové fakty sú testované s každou LHS pravidla. Dodatočne, ako bude popísané ďalej, nové fakty sú testované iba s LHS pravidla, ktorému sú najviac podobné. Výsledok: výpočtová zložitosť dosahuje hodnotu niečo nad O(RFP).

RETE algoritmus je realizovaný vybudovaním siete uzlov, kde každý z nich predstavuje jeden alebo viac testov, založených na testovaní LHS pravidla.
Fakty, ktoré sú pridané alebo odobrané z bázy faktov, sú spracovávané touto sieťou uzlov. Na dne siete sú uzly reprezentujúce jednotlivé pravidlá. Keď množina faktov preniká všetkými cestami nadol ku dnu siete, musí prejsť všetky testy na LHS konkrétneho pravidla. Táto množina sa state aktivovanou. Asociované pravidlo môže mať RHS vykonanú (fired) vtedy, ak aktivovanie nie je zrušené skôr ako odstránenie jedného alebo viacerých faktov z aktivovanej množiny.

Vnútri siete sú dva druhy uzlov: jedno-vstupové a dvoj-vstupové uzly.
Jedno-vstupové uzly vykonávajú testy na jednotlivých faktoch, zatiaľ čo dvoj-vstupové uzly vykonávajú testy cez fakty a zastávajú funkciu zoskupovania. Tretím pomocným typom uzlov sú koncové uzly.

3.3 Príklad na RETE algoritmus


Majme definované následujúce dve pravidlá:
 (defrule example-2      (defrule example-3
    (x)                     (x)
    (y)                     (y)
    (z)                     => )
    => )
môžu byť preložené do nasledujúcej siete:

        +----+  +----+  +----+     +----+   +----+  (jedno-vstupové uzly)
        | X? |  | Y? |  | Z? |     | X? |   | Y? |
        +----+  +----+  +----+     +----+   +----+
          \       /       |          \        /
        +------------+    |        +------------+
        |     +      |    |        |     +      |
        +------------+    |        +------------+
                  \       |              |          (dvoj-vstupové uzly)
                +------------+           |
                |     +      |           |
                +------------+           |
                      |                  |
            +----------------+     +----------------+
            | fire example-2 |     | fire example-3 |   (koncové uzly)
            +----------------+     +----------------+
Uzly označené X?, Y?, Z? atď. testujú, či fakt obsahuje dané dáta, zatiaľ čo uzly označené + si pamätajú všetky fakty a pravidlo odpália vždy, keď prijali dáta z ľavého aj pravého vstupu.

Pri spustení siete Jess odovzdá nové fakty každému uzlu zhora siete hneď, ako boli pridané do bázy faktov. Každý uzol berie vstup zhora a pošle svoj výstup smerom nadol.

Jedno-vstupový uzol obvykle prijíma fakty zhora, aplikuje na ne test a ak test prešiel, pošle fakt smerom nadol k nasledujúcemu uzlu. Ak test zlyhal, jedno-vstupové uzly jednoducho nič neurobia.

Dvoj-vstupové uzly musia integrovať fakty z ich ľavého a pravého vstupu, preto ich chovanie musí byť viac komplexné. Ľubovolné fakty dané na vstup dvoj-vstupového uzla môžu prispieť k aktivácii: prejdú všetkými testami, ktoré môžu byť aplikované na jednotlivé fakty.
Dvoj-vstupové uzly si preto musia zapamätať všetky fakty, ktoré sú im predložené na vstup, a pokúsiť sa zoskupiť fakty prichádzajúce na ich ľavé vstupy s faktami prichádzajúcimi na ich pravé vstupy a tak doplniť aktivované množiny. Dvoj-vstupový uzol má z toho dôvodu ľavú a pravú pamäť.

Vhodné je rozdeliť sieť do dvoch logických komponentov: sieť vzoriek obsahujúcich jedno-vstupové uzly, zatiaľ čo sieť spojov tvoria dvoj-vstupové uzly.

3.4 Optimalizácie zlepšujúce RETE algoritmus


Existujú dve jednoduché optimalizácie zlepšujúce RETE algoritmus:

1) Zjednotíme identické jedno-vstupové uzly v sieti vzoriek (šípky vedúce von z X? a Y? uzlov sú výstupy):

                    +--------------------------+
                    ^       +-------------+    |
                    |       ^             |    |
                    |       |             |    |
                  +----+  +----+  +----+  |    |
                  | X? |  | Y? |  | Z? |  |    |
                  +----+  +----+  +----+  |    |
                  /      /        /       |    |
        +------------+  /    +---/   +------------+
        |     +      |-+    /        |     +      |
        +------------+     /         +------------+
                  \       /              |
                +------------+           |
                |     +      |           |
                +------------+           |
                      |                  |
            +----------------+     +----------------+
            | fire example-2 |     | fire example-3 |
            +----------------+     +----------------+
2) Zjednotíme dvoj-vstupové uzly vykonávajúce rovnaké funkcie (integrovanie X,Y párov):
                  +----+  +----+  +----+
                  | X? |  | Y? |  | Z? |
                  +----+  +----+  +----+
                  /      /        /
        +------------+  /    +---/
        |     +      |-+    /
        +------------+     /
         |         \       /
         |       +------------+
         |       |     +      |
         |       +------------+
         |             |
         |   +----------------+
         |   | fire example-2 |
         |   +----------------+
   +----------------+
   | fire example-3 |
   +----------------+
Sieť vzoriek a spojovacia sieť sú teraz polovičnej veľkosti, ako boli pôvodne. Tento druh rozdelenia sa v reálnych systémoch vyskytuje veľmi frekventovane.

3.5 Kompilácia v Jesse


Využívanie siete v Jesse vidno po použití príkazu "watch-compilations". Keď je pravidlo prekladané, Jess vypíše reťazec znakov:
  examlpe-2: +1+1+1+1+1+1+2+2+t
Zakaždým, keď sa objaví +1 v reťazeci, bol vytvorený nový jedno-vstupový uzol. +2 indikuje nový dvoj-vstupový uzol. Teraz skompilujeme príklad example-3:
  example-3: =1=1=1=1=2+t
=1 vypíše vždy, keď je zdieľaný už existujúci jedno-vstupový uzol, =2 vypíše, keď je zdieľaný dvoj-vstupový uzol. +t predstavuje vytvorenie koncových uzlov. (Poznámka: počet jedno-vstupových uzlov je väčší než očakávaný. Jess vytvára oddelené uzly, ktoré testujú hlavu každej vzorky a jej dĺžku skôr, ako vykonajú oba z týchto testov v jednom uzle). Žiadne nové uzly nie sú vytvorené pre pravidlo example-3. Jess veľmi efektívne zdieľa už existujúce uzly.

RETE implementácia rozdielnych typov uzlov siete je v Jesse reprezentovaná rôznymi podtriedami Java triedy jess.Node.


4. Prepojenie Jessu s Javou

4.1 Vykonanie súboru s JESS kódom

Volanie JESS-u v programovom kóde napísanom v Jave je veľmi jednoduché s použitím nasledujúcich tried:
jess.Rete - jadro expertného systému JESS
jess.Jesp - syntaktický analyzátor JESS-u

Na vykonanie súboru, obsahujúceho CLIPS kód pre JESS, sa vytvorí v Jave Rete objekt a Jesp objekt, ktorému sa zadá súbor s CLIPS kódom. Samotný kód programu vykonáva funkcia Jesp.parse (boolean prompt), ako vidieť na nasledujúcom príklade :

import jess.*;
// trieda NullDisplay definuje rozhranie pre príkazový riadok
NullDisplay ND = new NullDisplay ();
// engine expertného systému JESS
Rete rete_engine = new Rete (ND);
// otvorenie súboru s programom v CLIPS kóde
FileInputStream FIS = new FileInputStream ("clips_code.clp");
// JESS_parser bude spracovávať pomocou rete_engine kód v súbore FIS
Jesp JESS_parser = new Jesp (FIS, rete_engine);
// vykonávaj jednotlivé príkazy súboru clips_code.clp
do
{
    try
    {
        // syntaktická analýza a vykonanie jednej konštrukcie
        JESS_parser.parse (false);
    }
    // všetky chyby v JESS sú zobrazované cez 'ReteExceptions'
    catch (ReteException RE)
    {
        RE.printStackTrace (ND.stderr());
    }
// až po koniec súboru, na ktorý ukazuje FIS
} while (FIS.available() > 0);

4.2 Pridanie voliteľných príkazov

Vyššie popísaný spôsob zahrňuje využitie iba minimálnej časti funkcií JESS-u. Mnoho ďalších funkcií dodávaných s JESS-om je implementovaných ako voliteľné triedy obsiahnuté v užívateľských balíkoch jess.Userpackage. Pri písaní kódu v Jave je možné pridať niektorý užívateľský balík (alebo aj všetky) nasledujúcim spôsobom, ktorý zabezpečí nezlyhanie systému, ak balík nie je k dispozícii:
// trieda NullDisplay definuje rozhranie pre príkazový riadok
NullDisplay ND = new NullDisplay ();
// engine expertného systému JESS
Rete rete_engine = new Rete (ND);
// zoznam užívateľských balíkov, ktoré sa pridávajú do systému
String [] packages = { "jess.StringFunctions",
                              "jess.PredFunctions",
                              "jess.MultiFunctions",
                              "jess.MiscFunctions",
                              "jess.MathFunctions",
                              "jess.BagFunctions",
                              "jess.reflect.ReflectFunctions",
                              "jess.view.ViewFunction" };
// v cykle vyskúša pridať užívateľský balík k funkciám systému
for (int i=0; i< packages.length; i++)
{
    try
    {
        // pridanie užívateľského balíka k funkciám systému
        rete_engine.addUserPackage
		((Userpackage) Class.forName(packages[i]).newInstance());
    }
    // balík nie je k dispozícii
    catch (Throwable t)
}

4.3 Vykonávanie samostatných príkazov 

Priame vykonávanie samostatných príkazov JESS-u v programe napísanom v Jave je možné pomocou metódy executeCommands, definovanej v triede Rete. Príkazy vykonávané metódou executeCommands môžu používať premenné JESS-u, ktoré sú pre tento účel interpretované v globálnom kontexte (defglobals). Nasledujúci príklad kódu názorne ukazuje vyššie popísaný spôsob. Zahrňuje využitie iba minimálnej časti funkcií JESS-u. Nasledujúci príklad popisuje vypísanie výsledku aritmetickej operácie, ktorý vypočíta príkaz JESS-u:
try
{
    rete.executeCommand("reset");
    rete.executeCommand("(assert (foo bar foo))");
    rete.executeCommand("run");
    // vypísanie výsledku operácie na obrazovku
    System.out.println(rete.executeCommand("(+ 37 5)"));
}
catch (ReteException RE)
{
    System.err.println("Foo bar error");
}

4.4 Metódy triedy Rete

Trieda Rete má niekoľko metód, z ktorých pre prácu s JESS-m sú najdôležitejšie tie, ktoré nám umožňujú pracovať s vytvorenými faktami a pravidlami expertného systému. Trieda Rete ďalej umožňuje aj vytváranie nových konštrukcií (facts, defrules, deftemplate, ...), čo sa však neodporúča robiť kvôli zachovaniu kompatibilty s budúcimi verziami JESS-u, pretože v nasledujúcich verziách sa bude JESS rozširovať o niektoré triedy, ako napr. jess.Defrule. Ďalšie dôležité metódy sú tie, ktoré umožňujú kontrolovať činnosť samotného expertného systému (run(), reset(), halt()).

Zoznam diagnostických metód v triede Rete:

    public synchronized Enumeration listDeftemplates
    public synchronized Enumeration listDefrules
    public synchronized Enumeration listFacts
    public synchronized Enumeration listActivations
    public synchronized Enumeration listDefglobals
    public synchronized Enumeration listUserfunctions

4.5 Použitie rozhrania ReteDisplay 

Každý Rete objekt je vytváraný s inštanciou rozhrania ReteDisplay. Metódy rozhrania ReteDisplay sú dvojakého typu. Prvé pracujú so vstupmi, výstupmi a chybovými hláseniami expertného systému, nakoľko nám to neumožňujú štandartné postupy použitia tried System.in a System.out v Jave. Druhé sú tie metódy, ktoré sa spúšťajú vždy, keď nastane určitá udalosť v expertnom systéme.

Definícia rozhrania ReteDisplay:

public interface ReteDisplay
{
    //nastavenie vstupu, výstupu, hlásenia chýb
    public java.io.PrintStream stdout ();
    public java.io.InputStream stdin ();
    public java.io.PrintStream stderr ();
    // metódy pre riadenie udalostí
    public void assertFact (ValueVector fact);
    public void retractFact (ValueVector fact);
    public void addDeffacts (Deffacts df);
    public void addDeftemplate (Deftemplate dt);
    public void addDefrule (Defrule rule);
    public void activateRule (Defrule rule);
    public void deactivateRule (Defrule rule);
    public void fireRule (Dedfrule rule);
    // sprístupnenie Applet-u pre Rete objekt
    public java.applet.Applet applet();
}
JESS obsahuje dve rôzne triedy, ktoré implementujú rozhranie ReteDisplay:
jess.NullDisplay - jednoduchá implemtácia rozhrania, definuje rozhranie príkazového riadku, presmerovanie štandardného vstupu a výstupu do Rete engine, neumožňuje použitie GUI.
jess.ConsoleDisplay - komplexnejšia implementácia rozhrania ako jess.NullDisplay, možnosť použitia GUI.

5. Záver

Hlavný význam Jessu spočíva v tom, že búra bariéru medzi klasickým programovaním v procedurálnych jazykoch a svetom umelej inteligencie. Doteraz si programátor musel často vyberať, či bude programovať v špeciálnom jazyku pre umelú inteligenciu a hľadať spôsoby, ako tento jazyk prepojiť s vonkajším svetom (službami operačného systému, perifériami), alebo sa pokúsil v procedurálnom jazyku napísať svoj vlastný "engine", ktorý mu vniesol do programu aké také inteligentné správanie.
S Jessom už nie je problém kedykoľvek si vytvoriť aj niekoľko "enginov", ktorým sa predhodí vstup na spracovanie a zároveň z jazyka Jess pristúpiť späť do sveta Javy.
Touto obojsmernou komunikáciou medzi dvoma odlišnými svetmi sa otvorila cesta pre používanie znalostných systémov aj na tých miestach, ktoré boli pre ňu doteraz neprístupné.

6. Bibliografia

1. Manuál jazyka Jess http://herzberg.ca.sandia.gov/jess/README.html
2. Zdrojové texty a príklady http://herzberg.ca.sandia.gov/jess/download.html
3. Stránka jazyka CLIPS http://www.ghg.net/clips/CLIPS.html
4. RETE algoritmus http://www.cis.temple.edu/~ingargio/cis587/readings/rete.html
5. RETE http://www.cse.unsw.edu.au/~cs9416/04-RETE/rete.html