Jess
Jess (Java Expert System Shell) è una shell per sistemi esperti e un linguaggio di scripting scritto interamente in Java, permette quindi di richiamare funzioni Java direttamente dal Jess o di incapsulare il Jess all’interno di un programma scritto in Java.
Si tratta di un sistema molto simile al CLIPS (C Language Integrated Production System) uno strumento per la realizzazione di sistemi esperti sviluppato negli anni 80, presso il laboratorio Lyndon B. Johnson Space Center della NASA negli Stati Uniti.
In Jess, come in CLIPS, è possibile definire regole di produzione (dette anche più semplicemente regole), costituite essenzialmente da un insieme di condizioni e da una sequenza di azioni. Se le condizioni di una regola sono soddisfatte essa può essere eseguita, e in questo caso verranno eseguite in sequenza le azioni in essa specificate.
I componenti principali sono:
- i fatti (fact);
- le regole (rule);
- il motore inferenziale (rules engine) o interprete.
L’insieme dei fatti e delle regole forma la Base di conoscenza (Knowledge Base) del sistema esperto.
1. I fatti
I fatti sono uno dei modi per rappresentare informazione (conoscenza), ogni fatto rappresenta un pezzo di informazione che risiede nella lista dei fatti (fact-list).
Un fatto è un elenco di stringhe racchiuso tra parentesi e viene inserito nella fact-list con il comando assert:
(assert (fatto da asserire))
Ecco alcuni esempi di inserimento di fatti:
(assert (padre giovanni marco))
(assert (è uomo mario))
(assert (un uomo ha due gambe))
Quando un fatto viene inserito nella fact-list il sistema gli assegna un numero in modo da poterlo identificare univocamente (fact address):
Per eliminare un fatto si usa il comando retract indicando il suo identificatore numerico:
(retract 2)
In fatti possono essere di due tipi:
- ordinati (ordered): sono quelli che abbiamo visto precedentemente, consistono in un simbolo seguito da una sequenza di zero o più campi separati da spazi e racchiusi tra parentesi tonde.In questi tipi di fatti l’ordine è fondamentale, infatti il fatto (Mario Rossi) è diverso dal fatto (Rossi Mario)
- non ordinati (unordered): non conta l’ordine, sono simili ai record dei linguaggi C e Pascal. Prima di poterli usare bisogna definire la propria struttura con il comando deftemplate:
(deftemplate persona ;nome del template
(slot nome ;nome del campo
(type SYMBOL)) ;tipo del campo
(slot cognome ;nome del campo
(type SYMBOL)) ;tipo del campo
(slot annoNascita ;nome del campo
(type INTEGER)) ;tipo del campo
(slot professione ;nome del campo
(type SYMBOL) ;tipo del campo
(default studente)) ;valore di default
Per inserire un fatto non ordinato si usa il comando assert nel seguente modo:
(assert persona (annoNascita 50) (nome Mario) (cognome Rossi))
Una cosa importante da notare è che i fatti sono case-sensitive e quindi il fatto (padre giovanni marco) è diverso da (padre Giovanni Marco).
2. Le regole
Affinché un sistema si possa definire esperto, è necessario fornirlo di regole che possano produrre conoscenza a partire dai fatti. Esse specificano un insieme di azioni che devono essere eseguite in una data situazione.
Una regola è definita con il comando:
(defrule NomeDellaRegola “commento”
(pattern_1)
(pattern_2)
. . .
(pattern_N)
=>
(action_1)
. . .
(action_M)
)
La parte precedente allo speciale simbolo => (uguale maggiore) si chiama antecedente (LHS: Left Hand Side), mentre quella che viene dopo si chiama conseguente (RHS: Right Hand Side). L’antecedente è un insieme di condizioni (pattern) che devono essere tutte soddisfatte (AND) perché la regola sia applicabile, mentre il conseguente è composto da un insieme di azioni che vengono svolte. È compito del motore inferenziale verificare le condizioni ed eseguire le opportune azioni.
Un esempio di regola è quella che trova i nonni a partire da una lista dei fatti nel quale sono indicati i padri delle varie persone. Decidiamo di indicare che “Mario è il padre di Luca” con il fatto ordinato (padre mario luca).
Chi è nostro nonno? Nostro nonno è il padre di nostro padre, quindi se x è il padre di y e y è il padre di z allora x è il nonno di y, in Jess definiamo questa regola:
(defrule R_nonno “regola che trova i nonni”
(padre ?x ?y)
(padre ?y ?z)
=>
(assert (nonno ?x ?z))
)
Quindi se nella fact-list sono presenti i seguenti fatti:
(padre mario luca)
(padre luca alberto)
la regola R_nonno scatterà con l’assegnazione: ?x = mario ?y = luca ?z = alberto
l’esecuzione della regola, che avviene quando viene dato il comando (run), provoca l’inserzione nella fact-list del fatto:
(nonno mario alberto)
3. L’interprete
Il funzionamento dell’interprete segue il ciclo riconoscimento-azione tipico dei sistemi a regole di produzione. A grandi linee il ciclo è strutturato come segue:
- riconoscimento: si confrontano le condizioni di tutte le regole di produzione con tutti i fatti contenuti nella base dei fatti; per ogni regola le cui condizioni sono soddisfatte, si inserisce la corrispondente attivazione nell’agenda (una regola può dar luogo anche a più attivazioni);
- azione: se l’agenda è vuota, l’esecuzione termina; altrimenti si preleva l’attivazione in testa all’agenda e la si esegue (eseguendo in sequenza le azioni specificate dalla regola corrispondente);
- si ritorna al passo 1.
L’inserimento delle attivazioni nell’agenda avviene secondo una strategia ben definita (depth, breadth, lex, mea, simplicity, complexity e random), inoltre il programmatore può influire direttamente sull’inserimento definendo la priorità (salience) di una regola. Il ciclo riconoscimento-azione ha inizio quando si sottopone all’interprete Jess il comando (run).
4. Utilizzare il Jess all’interno di un programma Java
La classe fondamentale è jess.Rete che implementa il motore inferenziale. Ogni oggetto jess.Rete ha la propria basa di conoscenza, l’agenda, le regole, …; per incapsulare il Jess all’interno di Java basta semplicemente creare uno oggetto jess.Rete e manipolarlo.
Rete r = new Rete();
r.excuteCommand(”(assert (padre mario luca))”);
r.run();


Recent Comments