Jess, The Rule Engine for the
Java Platform
Seminario per il Corso di laboratorio di Sistemi Intelligenti a cura di A. Gilitus
Sito ufficiale:
http://herzberg.ca.sandia.gov/jess/
Jess, The Rule Engine for the
Java Platform
Come usare il Jess:
• Interfaccia a riga di comando
• Comando batch
Interfaccia a riga di comando
Per lanciare l’interfaccia a riga di comando è
sufficiente digitare:
java jess.Main
A questo punto compare il prompt:
Jess>
in cui digitare i comandi come in CLIPS.
Es.
Jess> (assert (pippo))
Comando batch
Per caricare un programma scritto in Jess si
utilizza il comando batch:
Jess> (batch nomefile.clp)
Oppure specificare il file CLIPS sulla riga di
comando quando si carica l’ambiente di
Jess.
java jess.Main nomefile.clp
Jess, The Rule Engine for the
Java Platform
• Parallelo Jess/CLIPS
• Implementazione di Jess con Java
Parallelo Jess/CLIPS
• Differenze nell’utilizzo dei moduli
• Allowed-value
• Interfaccia Grafica
Differenze nell’utilizzo dei moduli
1.
2.
3.
4.
Non si dichiara il modulo MAIN. Regole, fatti,
template, ecc. che compaiono nel modulo MAIN
devono avere la dicitura MAIN:: davanti.
Non si usano import e export, a differenza del CLIPS
ogni modulo importa da tutti e esporta a tutti.
Ogni fatto dichiarato in un determinato modulo (per
es. nel modulo PIPPO) sarà distinto dal nome del
modulo stesso in working memory, per es. nel caso
di una assert(ciao) nel modulo PIPPO, si avrà il fatto: f1 PIPPO::ciao
Per riferirsi a fatti asseriti da altri moduli, è
necessario esplicitare il nome del modulo che li ha
asseriti.
Non si dichiara il modulo MAIN.
JESS
(deftemplate MAIN::solution (slot value
(default no)))
(deffacts MAIN::param
(solution (value no)) (maxdepth 0))
(deffacts MAIN::S0
(status 0 clear a NA) (status 0 on a b )
(status 0 on b c ) (status 0 ontable c
NA)
(status 0 ontable d NA) (status 0 clear
d NA)
(status 0 handempty NA NA))
(deffacts MAIN::final
(goal on a b) (goal on c d) (goal
ontable d NA) (goal on b c))
CLIPS
(defmodule MAIN (export ?ALL))
(deftemplate solution (slot value (default
no)))
(deffacts param
(solution (value no)) (maxdepth 0))
(deffacts S0
(status 0 clear a NA) (status 0 on a b )
(status 0 on b c ) (status 0 ontable c
NA)
(status 0 ontable d NA) (status 0 clear
d NA)
(status 0 handempty NA NA))
(deffacts final
(goal on a b) (goal on c d) (goal
ontable d NA) (goal on b c))
Non si usano import e export
JESS
(defmodule MAIN2)
(defrule got-solution
(declare (salience 100))
(solution (value yes)) =>
(assert (risolto))
(pop-focus)
)
(defrule pick
(status ?s on ?x ?y)
(status ?s clear ?x ?)
(status ?s handempty ? ?)
(maxdepth ?d)
(test (< ?s ?d))
(not (exec ?s pick ?x ?y))
=> (assert (apply ?s pick ?x ?y)))
CLIPS
(defmodule MAIN2 (import MAIN
?ALL)(export ?ALL))
(defrule got-solution
(declare (salience 100))
(solution (value yes)) =>
(assert (risolto))
(pop-focus)
)
(defrule pick
(status ?s on ?x ?y)
(status ?s clear ?x ?)
(status ?s handempty ? ?)
(maxdepth ?d)
(test (< ?s ?d))
(not (exec ?s pick ?x ?y))
=> (assert (apply ?s pick ?x ?y)))
Ogni fatto dichiarato in determinato
modulo sarà distinto dal nome del
modulo stesso in working memory
Es. le asserzioni nel modulo PIPPO,
compariranno in working memory nel
seguente modo:
f-1 PIPPO::ciao …
f-2 PIPPO::sono …
f-3 PIPPO::Pippo …
Per riferirsi a fatti asseriti da altri
moduli, è necessario esplicitare il
nome del modulo che li ha asseriti
es:
(defmodule NEW )
(defrule check-ancestor
(declare (salience 50))
?f1 <- (MAIN2::ancestor ?a)
(or (test (> ?a 0)) (test (= ?a 0)))
(MAIN2::news ?s)
(status ?s ?op ?x ?y)
(not (status ?a ?op ?x ?y))
=>
(assert (MAIN2::ancestor (- ?a 1)))
(retract ?f1)
(assert (diff ?a)))
Allowed-value
All’interno di un deftemplate si possono
dichiarare diversi slot, in CLIPS si possono
assegnare diversi valori a questi slot sotto
forma di valori permessi: allowed-value. In
Jess non sono ammessi.
Load-facts
In Jess è possibile caricare un intero blocco
di fatti memorizzati su file.
(load-facts nomefile)
Es. caricare la dichiarazione della mappa
del supermercato.
Interfaccia Grafica
Il Jess non ha un’interfaccia grafica come il
CLIPS. E’ stato pensato per essere
utilizzato tramite Java.
L’interfaccia grafica di CLIPS rende le
operazioni di debug molto semplici, in
Jess il debug è complicato, a meno che…

JessGUI
Implementazione di Jess con Java
Prima distinzione: scegliere chi sarà l'applicazione
pilota, cioè, colei che deterrà il controllo
sull'altra.
Il Jess consente di effettuare questa scelta:
- Java applicherà il controllo sul Jess
(consigliato, facile utilizzo)
- Jess applicherà il controllo su Java (Writing
GUI in Jess, Cap 7., Help di Jess, sconsigliato,
difficile utilizzo)
Java controlla il Jess
• Istanziazione di uno o più motori Jess.
• Il motore inferenziale Jess è basato sulla classe
Rete.
–
–
–
–
–
knowledge base,
agenda,
lista dei fatti,
stack dei moduli,
ecc.
• La classe Rete controlla tutto, o quasi, il motore
inferenziale
Utilizzo della classe Rete
Es.
import jess.*; public class ExSquare {
public static void main(String[] unused) {
try
{
Rete r = new Rete();
r.executeCommand("(deffunction square (?n) (return (* ?n ?n)))");
Value v = r.executeCommand("(square 3)");
// Prints '9'
System.out.println(v.intValue(r.getGlobalContext()));
}
catch (JessException ex)
{
System.err.println(ex);
}
} }
Livello di interazione
1. Si inizializza Jess e si costruisce il
programma Jess sfruttando i metodi della
classe Rete (tutto eseguito da Java), il
codice Jess risulta spezzato e annegato
in quello Java.
Pro e contro:
Difficile correzione del programma Jess,
caldamente sconsigliato.
Livello di interazione
2. Si inizializza Jess gli si fa caricare il
programma Jess e lo si esegue (possibilmente
utilizzando thread separati). Questo metodo
consente di mantenere una separazione netta,
o quasi, tra Java e Jess.
Pro e contro:
Mantenendo slegate le due esecuzioni è
possibile ottenere più che buoni risultati,
cambiare il codice Jess non comporta la
modifica del codice Java.
Livello di interazione
3. Evoluzione del punto 2., si possono applicare
“correzioni” al programma Jess prima o
durante l’esecuzione (inserendo, per esempio,
un fatto in knowledge base).
Pro e contro:
Si può utilizzare per un eventuale debug,
bisogna ricordarsi tutti i punti in cui si è
interagito con il Jess per eventuali modifiche.
Metodi di utilizzo più frequente
1.
2.
3.
4.
5.
6.
7.
8.
caricamento di un programma Jess,
reset del motore inferenziale,
comando di run,
comando di step,
metodo per controllare i fatti in knoledge base,
metodo per controllare lo stack dei focus,
metodo per controllare l’agenda,
utilizzo dei watch.
Caricamento di un programma
Jess
Utilizzo della classe JESP:
• carica il programma
• esegue il parse  controlla se ci sono
errori nel codice
Jesp, un esempio
public void caricaImpostazioni(){
try{
FileInputStream fis = new
FileInputStream("superLarge.jess");
Jesp j = new Jesp(new InputStreamReader(fis), rete);
do{
try{
j.parse(false);
}catch(JessException re){ re.printStackTrace(); }
}while (fis.available() > 0);
}catch(IOException e){ e.printStackTrace(); }
}
Reset, Run e Step
• reset()  esegue il reset del motore
inferenziale (come in CLIPS)
• run()  …
• run(1)  questo metodo run consente di
eseguire un certo numero step prima di
fermarsi.
Fatti, Focus e Agenda
• listFacts() restituisce un iteratore, i cui elementi
sono di tipo Fact.
• listFocusStack() non funziona bene, si consiglia
di usare il metodo getFocus() che ritorna il
nome del modulo in cima allo stack.
• listActivations(String nomeModulo)
restituisce un iteratore contenente le regole di
possibile attivazione.
nomeModulo riduce l’elenco delle regole
attivabili al solo modulo interessato
Watch
•
•
•
•
watchAll()
unWatchAll()
watch(int i)
unWatch(int i)
Jess controlla Java
• Previsione futuristica: creare le classi Java
che il Jess dovrà controllare.
• Istanziare le classi create tramite il Jess.
Un esempio
Jess> ;; Create the widgets
(defglobal ?*f* = (new java.awt.Frame "Button Demo"))
Jess> (defglobal ?*b* = (new java.awt.Button "Hello"))
Jess> ;; Define the deffunction
(deffunction say-hello "Unconditionally print a message" (?evt)
(printout t "Hello, World!" crlf))
Jess> ;; Connect the deffunction to the button
(?*b* addActionListener (new jess.awt.ActionListener say-hello
(engine)))
Jess> ;; Assemble and display the GUI
(?*f* add ?*b*)
Jess> (?*f* pack)
Jess> (set ?*f* visible TRUE)
WINDOW_CLOSING Event
Jess> ;; If the event is a WINDOW_CLOSING event, exit the program
(deffunction frame-handler (?evt)
(if (= (?evt getID) (get-member ?evt WINDOW_CLOSING))then
(call (get ?evt source) dispose)
(exit)))
Jess> ;; Connect this deffunction to the frame
(?*f* addWindowListener
(new jess.awt.WindowListener frame-handler (engine)))
Documentazione
• Consultabile online sul sito ufficiale:
http://herzberg.ca.sandia.gov/jess/
• Tutti i riferimenti alle classi del package
Jess sono consultabili attraverso le API
della documentazione.