Jess.pdf

Anuncio
Lenguaje de programación Jess
Java
Expert
System
Shell
Ejemplo introductorio
Problema de tipo puzzle en el cual hay cinco
casas, de diferente color, habitadas por
hombres de diferentes nacionalidades, con
diferentes mascotas, bebidas preferidas y
fumadores de ciertas marcas de cigarrillos.
Con ciertos datos, determinar:
–
–
¿Quién bebe agua?
¿De quién es la cebra?
Ejemplo introductorio
El inglés vive en la casa roja. El español tiene un perro.
La casa color marfil está inmediatamente a la izquierda
de la verde, donde vive el que bebe café.
El que bebe leche vive en la casa del medio. El que fuma
Old Golds también cría caracoles.
El ucraniano bebe té. El noruego reside en la primer casa
de la izquierda. El que fuma Chesterfields vive al lado del
que tiene el zorro.
El que fuma Lucky Strike bebe jugo de naranja. El
japonés fuma Parliaments. El que tiene un caballo vive al
lado del que fuma Kools, cuya casa es amarilla.
El noruego vive al lado de la casa azul.
Instalar JessDE
Plugings para Eclipse versión 3.1 o posterior.
Descargar Jess de http://www.jessrules.com/jess/download.shtml
En usuario ya registrado insertar el email
[email protected] y cliquear en:
Stable version Jess 7.1p2 source, docs and samples, zip format
Username: user1714
Password: noybgoc6
Licencia para uso académico.
Luego descomprimir el archivo en una carpeta.
Instalar JessDE
Salir de Eclipse.
Descomprimir todos los archivos de
Jess71p2/eclipse dentro del directorio (de
nivel más alto) de instalación de Eclipse.
Confirmar que existe una carpeta llamada
“eclipse/plugins/gov.sandia.jess_7.1.0"
Reiniciar Eclipse.
Verificar la instalación
Bajo el menú "Help" elegir "about Eclipse SDK"
Debe haber un ícono de Jess.
Cliquear y presionar en "Plug-in Details".
Se encuentra una lista de tres plugins.
Crear un nuevo proyecto Java.
Crear un nuevo archivo en ese proyecto y
nombrarlo "hola.clp".
(printout t "Hola mundo" crlf)
Ejecución en línea de comandos
C:\Jess71p2> bin\jess.bat
Jess, the Rule Engine for the Java Platform
Copyright (C) 2008 Sandia Corporation
Jess Version 7.1p1 8/6/2008
Jess> (+ 2 2)
4
Jess> (batch "..\\examples\\jess\\sticks.clp"
C:\Jess71p2> bin\jess.bat
examples\jess\sticks.clp
Jess el motor de reglas para la
plataforma Java
Para utilizarlo se deben especificar 'reglas'.
Es necesario proveer 'datos' de acuerdo al
problema.
Cuando se ejecuta el motor, las reglas pueden
ser disparadas.
Las reglas pueden crear nuevos datos, o
pueden realizar cualquier tarea que se pueda
realizar con Java.
Elementos Básicos
Símbolos
–
–
–
Números
–
Letras, dígitos, $*=+/.<>_?#.
Diferencia entre mayúscula y minúscula.
nil, TRUE, FALSE son símbolos especiales.
3
4.
5.643
5654L
6.0E4
1D son números válidos
Strings
–
–
–
Se denotan utilizando comillas dobles: "Hola".
\ es carácter de escape.
"\n" no es válido como nueva línea.
Elementos Básicos
Listas
–
Pares de paréntesis con cero o más símbolos.
(+ 3 2) (a b c) ("Hola mundo") ()
(bind ?x 2) son todas listas válidas.
–
Llamamos head al primer elemento de las listas.
–
Comentarios
–
–
; línea comentada
/* comentario
de bloque */
Elementos Básicos
Todo el código en Jess tiene la forma de
llamada a función.
No hay operadores. Algunas funciones tienen
nombres al estilo de los operadores de java.
Las llamadas a función en Jess son
simplemente listas.
Se pueden anidar llamadas a funciones.
Elementos Básicos
Ejemplos de llamadas a funciones:
–
–
(+ (+ 2 3) (* 3 3))
(batch "examples/jess/hello.clp")
Definición de funciones:
Jess> (deffunction max (?a ?b)
(if (> ?a ?b) then
?a
else ?b))
TRUE
Elementos Básicos
Variables
–
–
–
–
Identificadores que comienzan con '?'.
Los nombres pueden contener los siguientes
caracteres: '-',' _', ':' o '*'. No pueden contener '.'.
No se declaran previamente.
Jess> (bind ?a 123)
123
Jess> ?a
123
Elementos Básicos
Control de flujo
Jess> (bind ?i 3)
3
Jess> (while (> ?i 0)
(printout t ?i crlf)
(-- ?i))
3
2
1
FALSE
Memoria de Trabajo (Working
Memory)
Jess mantiene una base de conocimiento.
Las unidades de conocimiento son hechos
(facts).
Existen tres tipos de hechos: no ordenados,
oscuros y ordenados.
Las reglas sólo pueden reaccionar ante
agregado, eliminación o cambios en la
memoria de trabajo.
Cada hecho tiene una plantilla (template).
Memoria de Trabajo (Working
Memory)
Cada plantilla tiene un nombre y un conjunto
de slots (como una clase Java o una tabla de
una BD relacional).
Con el comando facts es posible ver una
lista de todos los hechos de la memoria de
trabajo.
Los hechos se pueden agregar mediante las
funciones assert, add y definstance.
Memoria de Trabajo (Working
Memory)
Una declaración deftemplate incluye:
–
–
–
–
–
–
un nombre,
una string de documentación (opcional),
una cláusula extends (opcional)
una lista de declaraciones (opcional) y
una lista de cero o más slots.
cada slot puede tener una lista de calificadores.
Hechos no ordenados
Tienen campos (slots) con nombre.
(auto (marca Ford) (modelo Explorer))
Se deben definir los slots previamente
mediante deftemplate.
(deftemplate auto "un auto específico"
(slot marca) (slot modelo) (slot color
(default blanco)))
Hechos no ordenados
Jess> (reset)
Jess> (assert (auto (modelo Megane)
(marca Renault)))
<Fact-1>
Jess> (facts)
f-0 (MAIN::initial-fact)
f-1 (MAIN::auto (marca Renault) (modelo
Megane) (color blanco))
For a total of 2 facts in module MAIN.
Hechos no ordenados
Un slot puede contener múltiples valores
Jess> (deftemplate caja (slot
ubicacion) (multislot contenido))
TRUE
Jess> (bind ?id (assert (caja
(ubicacion cocina) (contenido
espatula esponja sarten))))
<Fact-2>
Hechos no ordenados
Se puede modificar un hecho.
Jess> (modify ?id (ubicacion
comedor))
<Fact-2>
Se puede extender un hecho.
Jess> (deftemplate auto-usado
extends auto (slot kilometraje))
TRUE
Hechos Oscuros
Son hechos no ordenados que sirven como
'puentes' hacia objetos Java.
Se puede introducir un objeto Java en la
memoria de trabajo.
Jess> (deftemplate Cuenta (declare
(from-class Cuenta)(includevariables TRUE)))
Jess> (defclass Cuenta Cuenta)
Hechos Ordenados
En la mayoría de las oportunidades se utilizan
hechos no ordenados.
En algunos casos no tiene sentido dar
nombres a los slots (numero (value 6)).
Hechos ordenados son simplemente listas.
(padre-de pedro juan)
Jess> (deftemplate padre-de
(declare (ordered TRUE)))
El algoritmo Rete
Se deben aplicar continuamente sentencias ifthen (reglas) a un conjunto de datos (working
memory).
Para mejorar eficiencia.
Se implementa mediante la construcción de
una red de nodos.
Cada nodo representa uno o más tests
encontrados en el lado izquierdo de alguna regla.
El algoritmo Rete
Cada nodo inferior
(terminal) representa una
regla.
Un conjunto de tests que
atraviesa toda la red hacia
abajo activa y dispara la
regla.
Nodos de una entrada y
nodos de dos entradas.
El algoritmo Rete
Optimización
compartiendo nodos.
Aparecen nuevos nodos
que se pueden
compartir.
El algoritmo Rete
Se pueden observar los
nodos creados y compartidos
mediante el comando watch
compilations:
+1
– +2
– =1
– =2
– +t
Jess genera otros nodos.
–
Reglas
Una regla es similar a una sentencia if…then…
Las reglas se ejecutan cuando se satisface la
parte del if siempre y cuando el motor de
reglas se esté ejecutando (comando run).
Ejemplo:
Jess> (deftemplate person (slot
firstname) (slot lastname) (slot
age))
Reglas
Las reglas se definen mediante el constructor
defrule.
Jess> (defrule bienvenido-menor
"Saludo para niños"
(person {age < 3})
=>
(printout t "Hola niño!"
crlf))
Reglas
El lado derecho de las reglas debe contener
solamente patrones con posibilidad de
matchear con hechos del espacio de trabajo.
El lado derecho no puede contener llamadas a
función.
Siempre se debe ejecutar el comando reset
que dispara el hecho inicial (initial-fact).
Reglas
Jess> (deftemplate person (slot firstName) (slot lastName)
(slot age))
TRUE
Jess> (watch all)
TRUE
Jess> (reset)
==> f-0 (MAIN::initial-fact)
TRUE
Jess> (defrule bienvenido-menor
"Saludo para niños"
(person {age < 3})
=>
(printout t "Hola niño!" crlf))
Reglas
bienvenido-menor: +1+1+1+t
TRUE
Jess> (assert (person (age 2)))
==> f-1 (MAIN::person (firstName nil) (lastName nil) (age
2))
==> Activation: MAIN::bienvenido-menor : f-1
<Fact-1>
Jess> (run)
FIRE 1 MAIN::bienvenido-menor f-1
Hola niño!
<== Focus MAIN
1
Patrones simples
Se pueden declarar variables para referirse al
contenido de un slot.
(person (age ?a) (firstName ?f)
(lastName ?l))
Este patrón matchea cualquier hecho person.
Se asigna a ?a, ?f y ?l el contenido de age,
firstName y lastName de esa instancia
respectivamente.
Patrones simples
Jess>
(defrule teenager
?p <- (person {age > 12 && age <
20} (firstName ?name))
=>
(printout t ?name " is " ?p.age "
years old." crlf))
Patrones simples
Puede haber reglas con más de un patrón.
Jess> (defrule misma-edad-diferente-nombre
?person1 <- (person)
?person2 <- (person {age == person1.age
&&lastName != person1.lastName})
=>
(printout t "Se encontraron personas de "
?person1.age "años." crlf))
Patrones en profundidad
Jess> (deftemplate coordenadas (slot x)
(slot y))
Jess> (defrule ejemplo-1 (coordenadas (x
?x) (y ?y))
=>
(printout t "Coordenadas (" ?x ", " ?y
")" crlf))
Patrones en profundidad - Tests
Los descriptores de slots pueden incluir cierto
número de tests.
Los tests van después del nombre de las
variables separándose con un símbolo '&'
(and) o '|' (or).
Actualmente el nombre de la variable es
opcional.
Patrones en profundidad - Tests
Los patrones pueden ser:
–
Un valor literal:
(coordenada (x 1.0))
–
Una variable que fue asignada previamente:
(coordenada (x ?x))
–
Una expresión regular de java entre '/':
(person (name /A.*/))
Patrones en profundidad - Tests
–
Restricción de predicados: El caracter ':' seguido
de una llamada a función. En este caso el test se
satisface si la función retorna TRUE.
(coordenada (x ?x&:(> ?x 10)))
–
Restricción de valor de retorno: Un signo '='
seguido de un llamado a función.
(coordenada (x ?x) (y =(+ ?x 1)))
Patrones en profundidad - Tests
Una expresión regular de Java encerrada
entre '/':
(person (name /A.*/))
Cualquiera de los patrones anteriores
precedido por el caracter '~' (negación).
(coordinate (x ?x) (y ~?x))
Matching en slots múltiples
Jess> (defrule match-tres-items
(lista-almacen ? ? ?)
=>
(printout t "Hay una lista de tres items." crlf))
TRUE
Jess> (assert (lista-almacen huevos leche manteca))
<Fact-0>
Jess> (run)
Hay una lista de tres items.
1
Matching en slots múltiples
Jess> (defrule match-lista-completa
(lista-almacen $?list)
=>
(printout t "Necesito comprar " ?list crlf))
TRUE
Jess> (assert (lista-almacen huevos leche manteca))
<Fact-0>
Jess> (run)
Necesito comprar (huevos leche manteca)
1
Asignación de patrones
Jess> (defrule example-5-1
?fact <- (initial-fact)
=>
(printout t (call ?fact getName) crlf))
TRUE
Jess> (reset)
TRUE
Jess> (run)
initial-fact
1
Elementos condicionales
'and', 'or', 'not', 'exists', 'test', 'forall'.
Jess> (defrule no-impares
(not (numero ?n&:(oddp ?n)))
=>
(printout t "No hay números
impares." crlf))
Código Java dentro de Jess
El código Java:
Vector v = new Vector();
v.add("Hola");
System.out.println(v.lastElement());
Se puede insertar así:
(bind ?v (new Vector))
(call ?v add "Hola")
((get-member System out) println (?v lastElement))
Código Jess dentro de Java
La clase jess.Rete es el motor de inferencia.
Contiene los métodos run(), reset(), etc.
Para ejecutar otros comandos: eval(String)
Rete r = new Rete();
r.eval("(deffunction cuadrado (?n) (return
(* ?n ?n)))");
Value v = r.eval("(cuadrado 3)");
System.out.println(v.intValue(r.getGloba
lContext()));
Descargar