JESS Java Expert System Shell Dokumentation Inhaltsverzeichnis 1. 1.1. 1.1.1. 1.1.2. 1.1.3. 1.1.4. 2. 2.1. 2.2. 2.3. 2.4. 2.5. 2.6. 2.7. 2.8. 2.9. 2.10. 2.11. 2.12. 2.13. 2.14. 2.15. 2.16. 3. Einführung Erste Schritte mit JESS Entpacken Kompilieren von JESS Beispielprogramme Kommandozeileninterface Die JESS-Sprache Atome Zahlen Strings Listen Kommentare Funktionen Variablen Konstrukte Deffunctions Fakten Deftemplates Defclasses Deffacts Definstances Defrules Defglobals Abschließende Bemerkungen Inhalt 1. Einführung JESS ist ein Expertensystem, das vollständig in Java geschrieben wurde. JESS war ursprünglich eine Ableger von CLIPS, wurde dann aber immer mehr von Java beeinflusst. Mit JESS kann man seinen Java-Programmen und Applets „Vernunft einhauchen“. JESS 4.4. ist mit allen Java-Versionen ab Version 1.0.2. kompatibel. JESS 4.4. ist auch mit Java Version 1.1. kompatibel, obwohl Sie während des Kompilierens auf „deprecated“Warnungen stoßen werden, die Sie gefahrlos ignorieren können. Das ist der Preis der Preis der Kompatibilität. JESS 4.4. ist die letzte Version, die mit Java Version 1.0.2. kompatibel ist. Zukünftige Versionen von JESS werden nicht mehr mit Java unterhalb von Version 1.1. arbeiten. Dadurch verschwinden dann aber die „deprecated“-Warnungen. JESS unterliegt zum Zeitpunkt dieser Dokumentation ständiger Bearbeitung d.h., dass andauernd neue Features hinzugefügt werden. 1.1. Erste Schritte mit JESS 1.1.1. Entpacken Haben Sie die JESS-Version für Unix heruntergeladen, können Sie die Dateien mithilfe tar und uncompress entpacken: uncompress Jess-4.4.tar.Z tar xf Jess-4.4.tar Haben Sie die JESS-Version für Windows heruntergeladen, erhalten Sie eine .zip-Datei, die Sie mithilfe eines Win32-Packprogramm (z.B. Winzip) entpacken können. Bitte benutzen Sie nicht das Programm PKUNZIP, da es keine langen Dateinamen unterstützt. Nach dem Entpacken sollten Sie ein Verzeichnis namens Jess44 haben. In diesem Verzeichnis befinden sich die folgenden Dateien: Readme.hmtl jess/ jess/view jess/reflect examples/ jess/examples index.html Makefile Eine ausführliche JESS-Dokumentation auf Englisch. Dieses Verzeichnis enthält das JESS-Package. Hier enthalten sind die Quelldateien, die JESS implementieren. Andere implementieren JESS-GUIs und Kommandozeileninterfaces. Main.java implementiert das JESSKommandozeileninterface. Console.java ist eine sehr einfache GUIKonsole für JESS; ConsoleApplett.java ist ein Applet von dem selben Sachverhalt. Java-Quelltext, der das optionale JESS-Kommando view implementiert. Java-Quelltext, der optionale JESS-Kommandos implementiert, das Sie Java-Objekte von JESS aus erzeugen und verändern lässt. Ein Verzeichnis mit kleinen JESS-Beispieldateien. Ein Verzeichnis mit komplizierteren Beispielen, das auch JavaBeispieldateien enthält. Eine Webseite, die das JESS-Beispiel-Applet enthält. Es muß möglicherweise angepasst werden. Ein einfaches Makefile für JESS. Inhalt 1.1.2. Kompilieren von JESS JESS besteht aus einer Sammlung von Java-Quelldateien. Sie werden Sie zunächst kompilieren müssen. Wenn Sie über ein make-Tool verfügen (ein beliebiges Unix make; oder nmake oder GNU make unter Windows), können Sie dieses einfach ausführen und das beigefügte Makefile wird alles für sie kompilieren. Es kann sein, dass Sie es vorher ein wenig editieren müssen. Ansonsten benutzen Sie die folgenden Kommandos, um JESS zu kompilieren: javac jess/*.java (Unix) oder javac jess\*.java (Windows) Diese Kommandos funktionieren unter den Voraussetzungen, daß Sie einen Java Compiler (z.B. Sun’s JDK) installiert haben, und wenn Jess44/ Ihr aktuelles Verzeichnis ist. Sollten Sie Probleme haben, stellen Sie sicher, dass das Verzeichnis, in dem das Unterverzeichnis jess/ im CLASSPATH enthalten ist (einschließlich des aktuellen Verzeichnisses, repräsentiert durch den Punkt (.)). Versuchen Sie nicht, von innerhalb des Jess44/jess/ Verzeichnisses zu kompilieren. Es wird nicht funktionieren. Die in den Unterverzeichnissen Jess44/jess/view/ , Jess44/jess/reflect/ und Jess44/jess/examples/ enthaltenen optionalen Quelldateien werden nicht kompiliert, wenn Sie die obigen Instruktionen ausführen. Diese Dateien definieren das optionale DebugKommando view, die „reflection commands“ new, call, set, get, set-member und get-member und die Java-Objekte betreffenden Kommandos defclass und definstance. Diese können nur mit Java 1.1. oder neuer kompiliert werden. Kommandozeile für Java 1.1. oder neuer: Unix: javac jess/*.java jess/view/*.java jess/reflect/*.java jess/examples/*/*.java Windows: javac jess\*.java jess\view\*.java jess\reflect\*.java jess\examples\pumps\*.java jess\examples\simple\*.java 1.1.3. Beispielpogramme Es gibt einige Beispielprogramme, die Sie ausprobieren können: fullmab.clp, zebra.clp und wordgame.clp. fullmab.clp ist eine Version des klassischen Affe und Bananen – Problems. Um es von der Kommandozeile aus zu starten, tippen Sie: java jess.Main examples/fullmab.clp (Unix) java jess.Main examples\fullmab.clp (Windows) Inhalt und das Programm läuft und erzeugt mehrere Bildschirme voll mit Ausgaben. Um die gesamte Ausgabe lesen zu können, leiten Sie sich diese in eine Textdatei um: java jess.Main examples\fullmab.clp > fullmab.txt (Windows) Jede JESS-Quelldatei kann auf diese Weise ausgeführt werden. Viele einfache Programme, die in CLIPS geschrieben wurden, können unverändert in JESS benutzt werden. Die Beispiele zebra.clp und die wordgame.clp sind zwei klassische CLIPS-Beispiele, die zeigen sollen, wie JESS mit schwierigen Situationen umgeht. In den Verzeichnissen jess/examples/* finden Sie komplexere Beispiele, die alle sowohl Java- als auch JESS-Quellcode enthalten. Im allgemeine sind dies Beispiele, die zeigen sollen, wie man JESS und Java verbinden kann. 1.1.4. Kommandozeileninterface JESS hat ein interaktives Kommandozeileninterface. Tippen Sie einfach java jess.Main, um die Jess> Eingabeaufforderung zu erhalten. Um eine CLIPS-Quelldatei von der Eingabeaufforderung aus auszuführen, benutzen Sie das batch-Kommando: Jess> (batch myfile.clp) Sie können das system-Kommando benutzen, um einen Editor für die JESS-Quelldateien zu starten, bevor Sie sie mithilfe des batch-Kommandos ausführen. Die Klasse jess.Console ist eine grafische Version des JESS-Kommandozeileninterfaces. Die Ausgabe erfolgt in einem scrollbaren Fenster. Um es auszuprobieren, tippen Sie: java jess.Console Inhalt 2. Die JESS-Sprache JESS ist ein Interpreter für eine regelbasierte Sprache, die an CLIPS angelehnt ist. Mit dem Erbe von CLIPS ist JESS eine kleine Version von LISP, die aber doch ihre Eigenheiten hat. Dadurch wird JESS zu einem LISP-Interpreter, der in Java geschrieben wurde. Im folgenden werden einige Symbole verwendet. Ausdrücke, die in <spitzen Klammern> stehen, müssen vorhanden sein, Ausdrücke in [eckigen Klammern] sind optional. Ausdrücke, die mit einem plus (+) enden, können ein- oder mehrmals auftreten, Ausdrücke, die mit einem Stern (*) enden, können gar nicht oder mehrmals auftreten. Im allgemeinen unterliegt der JESS-Quelltext keinem Format. Man kann also im Quelltext einfach eine neue Zeile beginnen, ohne dass JESS dieses berücksichtigt (Zeilenumbrüche werden ignoriert). 2.1. Atome Das Atom bzw. Symbol ist das Kernkonzept der JESS-Sprache. Atome können mit Bezeichnern aus anderen Programmiersprachen verglichen werden. Ein JESS-Atom kann Buchstaben, Zahlen und die Sonderzeichen $ * = + / < > _ ? # und . enthalten. Ein Atom darf nicht mit einer Zahl beginnen. Es darf mit Sonderzeichen beginnen, obwohl einige von ihnen am Anfang eines Atoms eine besondere Bedeutung haben. Die folgenden Atome werden von JESS akzeptiert: name erster-wert moeglichkeit#1 _abc 2.2. Zahlen JESS bearbeitet Zahlen mithilfe der Java StreamTokenizer Klasse. Daher akzeptiert JESS nur einfache Fließkommazahlen und Ganze Zahlen. Die folgenden Zahlen werden von JESS akzeptiert: 3 4. 5.643 Inhalt 2.3. Strings Strings werden in JESS durch Anführungsstriche (“ “) gekennzeichnet. Der Backslash kann dazu benutzt werden, einen Anführungsstrich zum Teil eines Strings zu machen. Die folgenden Strings werden von JESS akzeptiert: “name“ “Hallo, Welt!“ “\“Unsinn \“ sagte er wörtlich.“ 2.4. Listen Die grundlegende Syntaxeinheit in JESS ist die Liste. Eine Liste besteht immer aus einem Paar runder Klammern und null oder mehr Atomen, Zahlen, Strings oder anderen Listen. Die folgenden Listen werden von JESS akzeptiert: (+ 3 2) (a b c) (“Hallo, Welt!“) () (deftamplate name (slot bar)) Das erste Element einer Liste wird in JESS der Kopf der Liste genannt. 2.5. Kommentare Die Kommentare des Programmierers beginnen in JESS mit dem Semikolon (;) und enden mit dem Ende der jeweiligen Zeile. Hier ist ein Beispiel für einen Kommentar: ; Dies ist eine Liste (a b c) Inhalt 2.6. Funktionen JESS beinhaltet eine Menge von eingebauten Funktionen, die Sie aufrufen können. Weitere Funktionen sind als Erweiterungen erhältlich. Man kann in JESS (siehe 2.9. Deffunctions) oder in Java auch selbst implementieren. Funktionsaufrufe in JESS benutzen eine Präfix-Notation. Eine Liste, deren Kopf der Name einer existierenden Funktion ist, kann als ein Ausdruck ausgewertet werden. So würde z.B. ein Ausdruck, der die Funktion plus zum Addieren der Zahlen 2 und 3 benutzt, wie folgt aussehen: (+ 2 3). Beim Auswerten ist der Wert des Ausdruckes die Zahl 5, und keine Liste mit dem Element 5. Im allgemeinen werden Ausdrücke als solche erkannt und im Kontext ausgewertet. Sie können Ausdrücke direkt in die JESS-Eingabeaufforderung eintippen. JESS wertet die Ausdrücke aus und gibt die Ergebnisse aus: Jess> (+ 2 3) 5 Jess> (+ (+ 2 3) (* 3 3)) 14 Beachten Sie dass die Ergebnisse sowohl als Gleitkommazahl als auch als Integerwert zurückgeliefert werden können. Der Typ des Rückgabewerts hängt von den Typen der übergebenen Argumente ab. Hier folgt nun eine komplette Liste der Funktionen, die in JESS 4.4. enthalten sind: ** + - / < <= <> = > >= abs agenda and assert assert-string bag batch bind build call clear close complement$ create$ defclass definstance delete$ div e engine eq eq* eval evenp exit exp explode$ external-addressp facts fetch first$ float floatp foreach format gensym* get get-member get-reset-globals get-salience-evaluation get-var halt if implode$ insert$ integer integerp intersection$ jess-version-number jess-version-string length$ lexemep listfunction$ load-facts load-function load-package log log10 lowcase max member$ min mod modify multifieldp neq new not nth$ numberp oddp open or pi ppdefrule printout random read readline replace$ reset rest$ retract retract-string return round rules run save-facts set set-member set-reset-globals set-salience-evaluation set-strategy setgen socket sqrt store str-cat str-compare str-index str-length stringp sub-string subseq$ subsetp sym-cat symbolp system time try undefinstance undefrule union$ unwatch upcase view watch while All diese Funktionen werden im JESS-Function-Guide detailliert beschrieben. Inhalt 2.7. Variablen Variablen in JESS sind Atome, die mit einem Fragezeichen (?) beginnen. Das Fragezeichen ist dabei ein Teil des Variablennamens. Eine normale Variable kann sich nur auf ein einzelnes Atom, eine einzelne Zahl bzw. einen einzelnen String beziehen. Eine Variable, deren erstes Zeichen das $-Zeichen ist (z.B. $?X) ist eine Multivariable, die sich auf eine spezielle Art von Listen , sogenannte Multifields bezieht. Allen Variablen werden mithilfe der bindFunktion Werte zugewiesen: (bind ?x “Der Wert“) Multifields werden im allgemeinen mithilfe von speziellen Multifield-Funktionen, wie create$ erzeugt. Dann können sie Multivariablen zugewiesen werden. (bind $?Einkaufsliste (create$ Eier Brot Milch)) Variablen brauchen und können nicht vor deren erster Benutzung deklariert werden. Eine Ausnahme sind die Defglobals. 2.8. Konstrukte Neben Ausdrücken und Multifields gibt es in JESS eine weitere Art spezieller Liste, Konstrukt genannt. Ein Konstrukt ist eine Liste, die dem JESS-System selbst z.B. eine Funktion hinzufügt (siehe z.B. Deffunctions). Ein Konstrukt liefert TRUE zurück, wenn es von JESS akzeptiert wurde, andernfalls wird FALSE zurückgegeben. Inhalt 2.9. Deffunctions Das deffunction-Konstrukt wird dazu benutzt, Funktionen zu definieren, die dann mit JESS benutzt werden können. Hier sehen Sie ein Beispiel für ein deffunction-Konstrukt: (deffunction <funktionsname> [<Kommentar>] (<parameter>*) <Ausdruck>* [<Rückgabewert>]) <funktionsname> muß ein Atom sein. Jeder <parameter> muß ein Variablenname sein (alle Funktionen benutzen die Übergabewerte-Semantik). Der optionale <Kommentar> ist ein String in Anführungszeichen, der die Bedeutung der Funktion beschreiben kann. Die Anzahl der <Ausdruck>-Ausdrücke kann beliebig sein. Der optionale <Rückgabewert> gibt den Rückgabewert der Funktion an. Die Rückgabe kann entweder durch die explizite Benutzung der return-Funktion erfolgen; es kann aber auch jede beliebige Variable zurückgegeben werden. Die Ablaufsteuerung in deffunctions erfolgt durch spezielle Ausdrücke, wie z.B. foreach, if und while. Die folgende deffunction gibt den zahlenmäßig größeren Wert der beiden übergebenen Argumente: (deffunction max (?a ?b) (if (> ?a ?b) then (return ?a) else (return ?b))) Das Problem könnte auch folgendermaßen gelöst werden: (deffunction max (?a ?b) (if (> ?a ?b) then ?a else ?b)) 2.10. Fakten JESS enthält eine Liste von Fakten bzw. Informationen über den derzeitigen Status des Systems. Fakten können geordnet oder ungeordnet sein. Geordnete Fakten sind lediglich Listen, deren Kopf ein Atom sein muss: (temperatur 21.5) (einkaufsliste brot milch wc-reiniger) (starte-arbeit) Ungeordnete Fakten sind strukturiert. Sie enthalten eine bestimmte Anzahl von slots, auf die mit ihrem Namen zugegriffen werden muß. Während geordnete Fakten ohne vorherige Deklaration benutzt werden können, müssen ungeordnete Fakten müssen mithilfe des deftemplate-Konstrukts definiert werden. Inhalt Fakten werden mit der assert-Funktion auf die Faktenliste gesetzt. Diese Liste kann mithilfe der facts-Funktion eingesehen werden. Fakten können von der Faktenliste entfernt werden (retract), wenn Sie deren Fakten-ID kennen: Jess> (assert (name wert)) <Fact-0> Jess> (facts) f-0 (name wert) For a total of 1 facts. TRUE Jess> (retract 0) TRUE Jess> (facts) For a total of 0 facts. TRUE 2.11. Deftemplates Um einen ungeordneten Fakt zu definieren, benutzen Sie den deftemplate-Konstrukt. (deftemplate <deftemplate-name> [<Kommentar>]) [(slot <slot-name> [(default <wert>)] [(default-dynamisch <wert>)] [(type <typespec>)])]+) Der <deftemplate-name> ist der Kopf der Fakten, die mit dem deftemplate-Konstrukt erzeugt wird. Es können beliebig viele slots zugewiesen werden. Der <slot-name> muß ein Atom sein. Der default slot-Bezeichner legt fest, dass der Standardwert des jeweiligen slots durch <wert> festgelegt wird. Der Abschnitt default-dynamisch wertet die gegebene Funktion jedes Mal aus, wenn ein neuer Fact, den dieses deftemplate benutzt, zugewiesen wird. Der Bezeichner type wird nur aufgrund der Kompatibilität mit CLIPS mitgeführt, wird aber von JESS ignoriert. Als Beispiel wird hier das folgende deftemplate definiert: (deftemplate automobile "ein bestimmtes Auto" (slot marke) (slot modell) (slot baujahr) (slot farbe (default weiss))) 2.12. Defclasses Mithilfe des defclass-Konstruktes kann man Java Bean als deftemplate benutzen. Nähere Beschreibungen hierzu entnehmen Sie bitte der JESS-Dokumentation, die der oben erwähnten .zip-Datei beigefügt ist. Inhalt 2.13. Deffacts Das deffacts-Konstrukt kann dazu benutzt werden, Fakten zu deklarieren, die bei jedem Start von JESS automatisch geladen werden sollen. (deffacts <deffacts-name> [<Kommentar>] <fact>+) Der primäre Zweck des <deffacts-name> ist die Dokumentation. Eine Instanz von deffacts kann beliebig viele Fakten enthalten. Ungeordnete Fakten müssen natürlich vor der Benutzung mittels deftemplate definiert werden. Das folgende deffacts-Konstrukt wird von JESS akzeptiert: (deffacts automobiles (automobile (marke Chrysler) (modell LeBaron) (baujahr 1997)) (automobile (marke Ford) (modell Contour) (baujahr 1996)) (automobile (marke Nash) (modell Rambler) (baujahr 1948))) 2.14. Definstances Definstances verhalten sich so zu defclasses, wie deffacts zu deftemplates. Während ein deffact-Konstrukt eine initiale Faktenliste definiert, definiert definstances eine Liste von Java-Objekten, die standardmäßig von JESS geladen werden sollen. 2.15. Defrules Der Hauptzweck eines Expertensystems wie JESS ist es, die Ausführung von Regeln zu unterstützen. Regeln sind in JESS ungefähr so wie IF...THEN... Verzweigungen in andeen Programmiersprachen. JESS prüft, ob eine oder mehrere dieser IF-Anweisungen wahr sind, um dann den entsprechenden THEN-Zweig auszuführen. Das defrule-Konstrukt wird in JESS benutzt, um solche Regeln aufzustellen: (defrule <defrule-name> [<Kommentar>]] [<salience-Deklaration>] [[<pattern-bindung> <- ] <pattern>]* => <aktion>*) Eine Regel besteht hauptsächlich aus einer Liste von Pattern und einer Liste von Aktionen. Die Pattern werden mit der Faktenliste verglichen. Wenn Fakten gefunden werden, sodass alle Pattern einer Regel erfüllt sind, feuert diese d.h., dass die Aktionen dieser Regel ausgeführt werden. Dabei ist zu beachten, dass auf der linken Seite einer Regel nur Fakten stehen dürfen, keine Ausdrücke. Eine Regel kann davon abgehalten werden zu feuern, wenn die Fakten, die zu ihrer Aktivierung führten, vorher retracted werden. Inhalt Wenn mehrere Regeln aktiviert sind, feuern Sie in der Reihenfolge des salience-Wertes. Je höher dieser Wert, desto eher werden die zu dieser Regel gehörenden Anweisungen ausgeführt. 2.16. Defglobals JESS unterstütz globale Variablen, die von der Einagbeaufforderung aus genauso sichtbar sind wie von innerhalb einer Regel oder deffunction. Sie werden mithilfe des defglobal-Konstrukts definiert. (defglobal [<varname1> = <wert1>]*) Beachten Sie, dass defglobals durch die Funktion reset auf Ihre Standardwerte zurückgesetzt werden müssen. 3. Abschließende Bemerkungen Diese Dokumentation wurde nur zusätzlich zu einer bereits vorhandenen, aber deutlich ausführlicheren Dokumentation erstellt, die bereits mit JESS mitgeliefert wurde. Diese war aber leider in englischer Sprache. Der Autor des vorliegenden Papiers hat sich streng an den Inhalt der originalen Dokumentation gehalten. Bestehen dennoch Unklarheiten, sollten Sie sich in der README.html vergewissern, die dem JESS-Paket beiliegt. Inhalt