A jugar con Drools!
Septiembre 23, 2008
Preparense porque se vienen nuevos post con este maravillos framework llamado JBoss Drools!
Si estan ansiosos y no pueden esperar a que yo escriba aca tienen!
Pagina oficial:
www.drools.org Aca tienen las descargas y la documentacion oficial.
Blog de los lideres del proyecto:
Un post mio sobre como podemos usar drools con jBPM:
http://salaboy.wordpress.com/2008/09/01/jugando-con-jbpm-12-jbpm-drools/
Con eso ya tienen para un rato de lectura!
Saludos y hasta pronto!
Una manera limpia de romper un alma
Septiembre 19, 2008

Annoyatron
Thinkgeek nunca va a dejar de sorprenderme, por 10 dolares podes tener la cordura de una persona.
NEAT (The NeuroEvolution of Augmenting Topologies) – Introducción
Septiembre 17, 2008
Introducción
NeuroEvolución (NE), es la forma de evolucionar redes neuronales usando algoritmos genéticos, esto ha demostrado ser muy eficiente en el refuerzo de tareas de aprendizaje.
NE busca en el espacio de los comportamientos de una red que funciona bien para una tarea en particular.
Por lo general, la topología de la red esta compuesta de una sola capa oculta de neuronas, donde cada neurona de esta capa tiene conectada cada una de las entradas y cada una de las salidas.
NE busca en el espacio de los pesos de las conexiones de toda la red permitiendo así que las redes altamente performantes se reproduzcan. Esto se logra con el apareamiento (crossover) de los vectores de pesos de las conexiones de toda la red, sumándole a este apareamiento una mutación arbitraria.
De esta manera funcionan los NE de topología fija, ya que optimizan los pesos de las conexiones que determinan la funcionalidad de la red.
A pesar de esto, los pesos de las conexiones no son el unico aspecto de las redes neuronales que contribuyen en su comportamiento. La topologia, o estructura, de una red neuronal tambien afecta a su funcionalidad.
La modificacion de la estructura de la red ha demostrado ser eficiente como parte del entrenamiento supervisados.
La pregunta que se nos plantea es:
La evolución de la topologías y los pesos de las conexiones nos van a dar alguna ventaja sobre las topologías fijas?
Si una función continua puede ser aproximada por una Red, para que vamos a esforzarnos permutando diferentes topologías?
Las respuesta hasta ahora a estas preguntas son bastantes inconclusas.
NEAT fue diseniado para tomar ventaja de la estructura como forma de minimizar la dimensionalidad de la búsqueda sobre el espacio de conexiones. Si la estructura esta evolucionada, esta topología esta minimizada y crece incrementalmente, lo cual resulta en ganancias en la velocidad de aprendizaje de la red.
Esta evolución y ganancia se va notando a lo largo del proceso de evolución y no solamente al final de todo el ciclo evolutivo.
Evolucionar una estructura incrementalmente presenta varios desafíos técnicos:
- Hay alguna representación genética que permita que distintas topologías se apareen (crossover) de manera que el resultado signifique algo?
- Como podemos proteger a las innovaciones de la topología (que necesitan algunas generaciones para ser óptimas) para que no desaparezcan de la población prematuramente?
- Como las topologías pueden ser minimizadas durante la evolución sin la necesidad de una función de “encaje” (fitness) que mida la complejidad de la misma?
NEAT se encarga de responder estas preguntas y dar una solución elegante, la cual iremos viendo en los siguientes posts.
RETE + NEAT = REAT??
Septiembre 17, 2008
En Este post bastante descolgado de los temas que actualmente toco en este blog, me va a servir como centro de investigación sobre la mezcla de estos temas con el fin de ver si pueden convivir y lograr algún resultado interesante.
Para empezar voy a tratar de describir cada uno de los temas muy por arriba y luego tratare de empezar a relacionarlos y profundizar en cada uno de ellos y en sus vínculos.
Empecemos por RETE:
RETE (red en latín) es un algoritmo muy utilizado en sistemas de reglas de producción ya que su funcionalidad principal es la de encontrar coincidencias entre patrones de manera muy eficiente. En estos sistemas por lo general necesitamos realizar comparaciones entre hechos y reglas de negocio con el fin de realizar inferencias sobre los mismos. Esto debe hacerse de una manera eficiente para que el sistema sea escalable y performante.
Por supuesto aparece el termino regla de producción que hace referencia a una regla compuesta por condición y acción. Donde en la condición especificamos un set de restricciones que van a condicionar la ejecución de la acción.
RETE funciona armando una red de nodos, donde cada uno de estos nodos se corresponde con una condición en la LHS (Left hand side / representa las restricciones en la parte condicional de una regla de producción), por lo tanto un camino desde el nodo raíz hasta un nodo hoja representaría toda una regla de producción.
Mas adelante, tratare de aclarar los distintos tipos de nodos que utiliza una red RETE, ya que esto ayudara bastante a comprender como funciona el algoritmo.
Seguimos con NEAT:
NEAT (NeuroEvolution of Augmenting Topologies / NeuroEvolución para el crecimiento de las topologías) se caracteriza por ser una técnica de NeuroEvolución, es decir, una técnica que utiliza algoritmos genéticos para evolucionar redes neuronales.
NEAT en particular se caracteriza por codificar de alguna manera la topología de la red neuronal y hacerla evolucionar generación tras generación, logrando así optimizar su funcionamiento.
Por lo general los algoritmos de NeuroEvolución se separan en dos ramas:
- Aquellos que se encargan de evolucionar los pesos en las conexiones en una red neuronal.
- Aquellos que se encargan de evolucionar tanto la topología de la red como los pesos en las conexiones de una red neuronal.
En este caso NEAT opta por la segunda opción, por lo cual vamos a ver como cuando aplicamos NEAT los pesos de las conexiones dentro de la red van evolucionando y a su vez se crean nuevos nodos y nuevas conexiones dentro de nuestra red como parte de esta evolución.
Como podran notar tanto RETE, como NEAT son temas bastantes complejos que incluyen mucho otros temas que hay que investigar para poder dominarlos y utilizarlos en la vida cotidiana. Para esto voy a listar los temas a investigar y las fuentes que pienso utilizar en dicha investigación:
RETE:
- Algoritmo, funcionamiento, características principales, lugares comunes de uso, extensiones de RETE.
NEAT:
- Algoritmo, funcionamiento, soporte teórico, pruebas y teorías
- Algoritmos geneticos + Redes neuronales + Programacion evolutiva
NEAT + RETE = REAT:
- Meta final de la investigación: http://www.evolvablerules.org/ (Greg Barton)
Como podemos ver en http://www.evolvablerules.org/ Greg Barton propone adaptar NEAT a RETE, lo cual causaría que la topología de la red RETE evolucione tanto como las reglas de producción que se definan.
Para lograr esto, sin duda alguna, hay que analizar muy bien NEAT y la topología especifica de RETE, así tanto como la codificación de los genes para los distintos tipos de nodos en RETE.
Esto no suena tarea facil para nada, por lo cual como primeros pasos voy a empezar enfocandome en NEAT y ver como se comporta con implementaciones reales, al menos simples.
Que feo es hacerse auto propaganda.
Septiembre 17, 2008
Es bastante feo el hecho de hacerse propaganda a uno mismo, la verdad nunca lo habia pensado.
Para ser mas claro, siempre pensé que la mejor propaganda para uno mismo es la que le hacen los demas o sus acciones pasadas.
Pero hoy, revisando mis mails, en la lista del foro oficial de jBPM mencionaron mi nombre y eso me lleno de orgullo, me hizo sentir realmente parte de esta especial comunidad. Mas aun si los comentarios vienen de un grande de la lista como kukeltje quien se declara a si mismo:
“A kind jBPM user and forum ‘addict’”
Aca les dejo el link, no para hacerme propaganda a mi mismo, sino para que si algun otro entisiaste de jBPM crea post al respecto, se anuncie en este thread del foro oficial de jBPM!
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4176927#4176927
Saludos!
Actualización: Mas auto propaganda en un nuevo blog creado para reunir todos los blogs de jBPM en todos los idiomas: http://planetjbpm.wordpress.com/
Actualización 2: Otro grande de los foros de JBoss hizo una resenia de este blog: http://www.jorambarrez.be/blog/2008/09/19/blogs-about-jbpm/
Actualización 3: Otro blog de un Ingeniero de Valencia, España me menciono:
http://www.workflowsworld.com/2008/10/salaboy-jbpm-en-castellano/
Jugando con jBPM #13 – Swimlanes a nivel conceptual
Septiembre 1, 2008
Es algo sobre lo que se pregunta bastante, ya que es un concepto que esta asociado con el modelado de procesos en general. Para no confundir, podemos definir a una swimlane como un rol del proceso, para ser mas especificos, podriamos decir que vamos a usar una swimlane cuando en un proceso que estemos modelando necesitemos especificar que un set de tareas deben ser realizadas por la misma persona, ya que esta es la que conoce el contexto de esas tareas para una instancia del proceso en particular.
Por lo tanto el comportamiento que vamos a obtener en jBPM es el siguiente:
- Definimos (modelamos) varias tareas asignadas a una swimlane
- Cuando la primer tarea de la swimlane se instancia, se llama al AssignmentHandler correspondiente y se asigna un actor a la swimlane
- Cuando la segunda tarea de la swimlane se instancie, se recupera el actor ya asignado por el AssignmentHandler y se asigna este a la tarea.
- Así para el resto de las tareas que estén asignadas a la swimlane.
Por lo tanto debemos tener cuidad de no aplicar un assignment handler a las tareas que se encuentran con una swimlane especificada.
Notas o aclaraciones nuevas:
Voy a tratar de en un par de puntos aclarar algunos conceptos que puede ayudar:
- En la definicion del proceso definimos task-node y task.
- Las task-nodes contienen 0 o mas task, las cuales se instancian dinámicamente (por defecto) cuando el flujo del proceso llega al task-node que las contiene
- En el momento de instanciación de cada una de las tareas (tasks dentro del task-node) se llama al correspondiente AssignmentHandler que esta definido en cada tarea.
- En un caso normal este AssignmentHandler resuelve a que actor del proceso le corresponde realizar la tarea y asigna al campo ActorId el nombre del actor obtenido. (También esta el caso de pooled actors pero no viene al tema)
- En el caso de que haya varias tareas a lo largo de varios task-nodes asociadas a un swimlane, genera otro comportamiento, que describo a continuación:
- Cuando el flujo de ejecución del proceso llega al primer task-node que contiene una tarea la cual esta asociada a una swimlane, esta tarea se instancia y se llama al assignment que tenga asociado la swimlane. Este AssignmentHandler tiene la particularidad que solo va a ser invocado por la primer tarea que se instancie y que este asociada con la swimlane. Lo que significa que cuando se instancie la segunda tarea asociada a la swimlane, el actor ya estará resuelto y deberá llamarse al AssignmentHandler correspondiente. Todo esto se logra manteniendo una ” instancia” de la clase SwimlaneInstance con el actor ya resuelto y recordándola (o sea persistiendo la) para que las nuevas tareas no tengan que realizar la logica de asignación nuevamente.
Espero que haya quedado un poco mas claro, prometo subir un ejemplo para discutir mas adelante.
Saludos!
Jugando con jBPM #12 – jBPM + Drools
Septiembre 1, 2008
Bueno como siempre, la idea del post es tratar de mostrar alguna funcionalidad de jBPM. Pero en este caso nos vamos a fusionar con otro framework muy importante dentro de la suite de productos de JBoss. Estamos hablando de JBoss Drools, este framework pretende cumplir todas las funcionalidades de un BRMS (Business Rule Management System – Sistema de administración de Reglas de Negocio).
En este caso vamos a ver un ejemplo sencillo de como podemos usar a Drools dentro de un ActionHandler de jBPM.
Para empezar con el ejemplo vamos a ver el gráfico del proceso del negocio que vamos a utilizar:
Este proceso básicamente se encargara de obtener los datos de una persona (de algún modo, podría ser una tarea humana cargar los datos de la persona) y con estos datos automáticamente se categorizara la persona teniendo en cuenta su edad, su sueldo, su categoría de trabajo, si posee vehículos, etc. Este es un proceso muy común en los análisis de riesgo crediticio, o también podría ser parte de la decisión para dar un seguro. La idea es que esta categorización se haga de manera automática con el motor de inferencias que nos provee Drools y de paso aprovechar de separar esta lógica de categorización dejándola afuera del código Java compilado, haciendo que esta sea mucho mas flexible a cambios. Sin dejar de lado la ventaja de que con los DSL (Domain Specific Language – Lenguajes Específicos de Dominio) podemos enmascarar las reglas definidas en lenguaje de Drools a algo muy parecido al lenguaje natural. (Mas de esto en un futuro post)
Entonces pasamos directamente a ver código y los pre-requisitos que necesitamos para que todo esto ande.
Como ya explique en post anteriores para que jBPM ande necesitamos sus dependencias, de la misma manera Drools tiene las suyas. Para obtener estas dependencias nos dirigimos a la pagina oficial de Drools y descargamos los binarios (Aprox. 50 megas)
Bajamos los binarios de Drools (Drools 4.0.7 Binaries):
http://www.jboss.org/drools/downloads.html
También recomiendo bajar el plug-in para eclipse, el cual nos hará las cosas mucho mas fáciles a la hora de escribir las reglas y sus correspondientes DSLs.
Drools 4.0.7 Eclipse Europa 3.3 Workbench (funciona para Ganymede también)
Una vez que tengamos esto descargado, necesitaremos descomprimirlos por ahí y luego crear una User Library en eclipse con los jars de Drools y sus correspondientes dependencias (que se encuentran en el directorio /lib).
(Para los que les interese Drools, recomiendo los ejemplos que hay en la pagina de downloads y la documentación oficial)
Una vez que tenemos los plug-ins instalados (jBPM y Drools) y las dependencias de ambos en nuestro proyecto, ya estamos listos para ver el codigo del proceso mostrado anteriormente.
Primero vamos al nodo (de tipo node) Obtener Persona, el cual tiene un ActionHandler asociado que posee el siguiente código:
public void execute(ExecutionContext context) throws Exception {
Persona persona=new Persona();
persona.setEdad(45);
Trabajo trabajo = new Trabajo();
trabajo.setPuesto(Puesto.GERENTE);
trabajo.setSueldo(50000);
persona.setTrabajo(trabajo);
ArrayList<Vehiculo> vehiculos = new ArrayList<Vehiculo>();
Vehiculo vehiculo=new Vehiculo();
vehiculo.setValor(130000);
vehiculo.setModelo("Audi A3");
vehiculos.add(vehiculo);
persona.setVehiculos(vehiculos);
context.setVariable("persona", persona);
context.leaveNode();
}
Como se puede observar en este ActionHandler solo armamos un objeto persona, la idea en la realidad seria que sacáramos de algún lado (como por ejemplo de una base de datos, o un servicio) este objeto. Una vez que tenemos este objeto Persona, lo asignamos a una variable de contexto y continuamos la ejecución del proceso.
Al continuar la ejecución, el proceso llega al nodo llamado Categorizar, el cual también tiene un ActionHandler asociado, el cual se encarga de levantar una Sesion de Drools para ejecutar las reglas que vamos a ver mas adelante. Vemos el codigo de este ActionHandler:
public void execute(ExecutionContext context) throws Exception {
//Creamos un paquete de reglas a partir del archivo categorizar.drl
PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl(new InputStreamReader(this.getClass().getResourceAsStream("/categorizar.drl"));
//Con este paquete de reglas creamos un RuleBase
RuleBase ruleBase = RuleBaseFactory.newRuleBase();
ruleBase.addPackage(builder.getPackage());
//Con este rule base instanciamos una nueva Session Stateful de reglas.
StatefulSession session = ruleBase.newStatefulSession();
//Buscamos en el contexto el objeto persona anteriormente obtenido
Persona persona=(Persona)context.getContextInstance().getVariable("persona");
//insertamos este objeto a la Working Memory como un fact
session.insert(persona);
//Creamos un objeto de tipo Salida que va a contener los resultados de las ejecuciones de la reglas
//Y lo agregamos como una variable global
Categoria categoria=Categoria.BAJA;
Salida salida=new Salida();
salida.setCategoria(categoria);
session.setGlobal("salida", salida);
//Una vez que tenemos las reglas (en el paquete) y los hechos insertados en la WM
//Disparamos las reglas
session.fireAllRules();
session.dispose();
//Buscamos los resultados y los guardamos en una variable del contexto del proceso
context.getContextInstance().setVariable("categoria", salida.getCategoria());
//Continuamos la ejecucion
context.leaveNode();
}
Para los que recién comienzan con Drools este código suele ser bastante traumático, ya que se hacen varias cosas bastantes inexplicables a simple vista. Para tratar de explicar un poco lo que estamos haciendo veamos el siguiente gráfico que explica como generamos un paquete de reglas, que nos va a servir para inferir sobre nuestros objetos.
Como observamos en el gráfico y en el código vamos a armar un paquete de reglas partiendo de una definición de reglas que en nuestro caso esta en un archivo drl llamado categorizar.drl (también podría estar en una definición en xml de las reglas). Como podemos ver esta tarea la tiene encargada la clase PackageBuilder, la cual compila y genera el código que termina resultando en un paquete de reglas. Una vez que tenemos este paquete de reglas (que no es mas que un resultado binario y optimizado para la ejecución de nuestras reglas) creamos una nueva instancia de la clase RuleBase a la cual le agregamos el paquete que acabamos de generar. Esta clase RuleBase va a ser la encargada de tener todos los paquetes de reglas (por ende todas las reglas que se encuentren en esos paquetes) para que el motor de inferencias pueda ejecutarlas contra los hechos (o facts en ingles, que son nuestros objetos) que se van a encontrar en la Working Memory (es una memoria especial donde nosotros almacenamos nuestros hechos/objetos)
Con los siguiente gráficos de la documentación oficial espero que se aclara un poco el panorama:
Cuando el flujo de ejecución llega a este nodo, vamos a notar que Drools se pone a trabajar, lo que significa que hasta este momento, no se había hecho uso de Drools, por esto vamos a notar una demora en este nodo. Como resultado de este nodo guardamos una variable llamada categoría que decidirá en el siguiente nodo que acción hay que ejecutar.
Lo único importante que nos esta faltando ver es el archivo de reglas llamado categorizar.drl:
package com.sample.rules
import com.sample.action.dominio.Persona; import com.sample.action.dominio.Persona.Categoria; import com.sample.action.dominio.Vehiculo; import com.sample.action.dominio.Trabajo; import com.sample.action.dominio.Trabajo.Puesto; global com.sample.action.output.Salida salida;
rule "Evaluar Categoria Alta"
when
$persona : Persona ( edad > 35)
$trabajo : Trabajo(puesto == Puesto.GERENTE, sueldo > 10000) from $persona.trabajo
exists ($vehiculo : Vehiculo(valor > 40000) from $persona.vehiculos)
then
System.out.println("Categoria Alta");
salida.setCategoria(Categoria.ALTA);
end
rule "Evaluar Categoria Media"
when
$persona : Persona ( edad > 21 )
$trabajo : Trabajo(puesto == Puesto.ESCLAVO, sueldo < 6000) from $persona.trabajo
exists ($vehiculo : Vehiculo() from $persona.vehiculos)
then
System.out.println("Categoria Media");
salida.setCategoria(Categoria.MEDIA);
end
rule "Evaluar Categoria Baja"
when
$persona : Persona ( edad > 21 , edad < 35)
$trabajo : Trabajo(puesto == Puesto.ESCLAVO, sueldo < 6000) from $persona.trabajo
not (exists ($vehiculo : Vehiculo() from $persona.vehiculos))
then
System.out.println("Categoria Baja");
salida.setCategoria(Categoria.BAJA);
end
Como podemos ver son reglas muy sencillas y fáciles de leer. Y lo mejor de todo es que estas reglas las tenemos centralizadas en este archivo drl, lo cual nos hará la vida mucho mas fácil cuando estas cambien y tengamos que adaptarnos a los cambios.
Espero que haya servido de algo el post, me imagino que le falta mucho detalle de como funciona Drools y como es la sintaxis de las reglas y que podemos hacer dentro de ellas. Pero ahondare en siguientes post, la finalidad de este era mostrar rápidamente como podíamos integrar muy desacoplada mente Drools con jBPM.
Espero comentarios, ya que me imagino que hay muchas cosas sobre el post que pueden no quedar claras.



