La Plataforma JADE para desarrollo de Agentes

Introducción

Jade (Jave Agent Development Environment) es un ambiente robusto basado en el estandar FIPA para ejecutar systemas de agentes distribuidos. Fue desarrollado en Italia conjuntamente por el CSELT (Centro Studi e Laboratori Telecommunicazioni) y el Computer Engineering Group de la Universidad de Parma. El sitio oficial de JADE es http://jade.cselt.it

En este proyecto se usara JADE por las siguientes razones:



Instalación

Para instalar JADE es necesario descargar el archivo JADE-bin-3.3.zip del sitio oficial. Después se extraen los archivos en el directorio raíz con el nombre c:\jade con el fin de hacer más rápida la conexión con el editor y el compilador de java. Se debe tener instalado previamente Java Run Time Enviroment (JRE) y el kit de desarrollo de Java (JSDK ). También deben existir las direcciones del compilador y las librerias de java en el PATH de Windows (por ejemplo c:\java\bin y c:\java\lib) . Es importante que NO se ELIMINE la ruta anterior, solo se deben agregar las lineas al PATH existente. Por último se debe establecer el CLASSPATH para incluir los archivos jar que estan en el subdirectorio “lib” de jade. Para ello en una ventana de sistema ejecutamos el comando:

set CLASSPATH=%CLASSPATH%;.;c:\jade\lib\jade.jar; c:\jade\lib\jadeTools.jar; c:\jade\lib\Base64.jar; c:\jade\lib\iiop.jar


Si hay problemas otra opción es abrir “Propiedades” en “Mi pc”, elegir la pestaña “Opciones avanzadas “ y luego seleccionar “Variables de entorno”. El cuadro de diálogo que aparece es como se muestra a continuación.



Figura 1. Creacion de variables de entorno

Por último crear una nueva variable llamada CLASSPATH. Como valor se puede pegar la linea

%CLASSPATH%;.;c:\jade\lib\jade.jar; c:\jade\lib\jadeTools.jar; c:\jade\lib\Base64.jar; c:\jade\lib\iiop.jar


Agentes RMA, AMS y DF


Si JADE se instaló con éxito será posible iniciar la plataforma llamando al agente principal RMA.


RMA (Remote Management Agent). Un RMA es un objeto o instancia de la clase jade.tools.rma.rma que es la clase que ejecuta la interfaz gráfica de la plataforma JADE. Un RMA ofrece un acceso rapido a la plataforma por medio de barras de menu y de herramientas. Permite visualizar el estado de los agentes ordendos por contenedores y enviar mensajes entre estos con un click.


Un RMA puede ser inicializado con cualquiera de los siguientes commandos en una ventana de sistema:


  1. java jade.Boot myConsole:jade.tools.rma.rma)

  2. java jade.Boot -gui

La primera línea ejecuta un agente RMAde la clase jade.tools.rma.rma con el nombre myConsole. La segunda línea ejecuta la plataforma sin un nombre especifico. La interfaz gráfica se muestra a continación.




Figura 2. Interfaz gráfica del RMA



Un RMA almacena uno o más contenedores de agentes y cada contenedor puede organizar a varios agentes. En la imagen anterior, el RMA tiene un solo contenedor llamado Main con tres agentes, el RMA, DF y AMS. Es posible iniciar varios contenedores en una misma plataforma siempre y cuando tengan nombres diferentes.



AMS (Agent Management System) es el agente manejador del sistema y por tanto quien tiene el control de la plataforma. Provee los nombres de los servicios y se asegura que cada agente tenga un identificador único. Es posible crear o matar agentes en contenedores remotos accesando al AMS.


DF (Directory Facilitator). Provee el sevicio de páginas amarillas, es decir es un registro centralizado de las IDs asociadas a la descripción de los servicios de los agentes.


A continuación se muestra el ejemplo de una red de agentes comunicados por dos plataformas. La plataforma1 tiene dos contenedores almacenados en el contenedor principal y la plataforma2 tiene un solo contenedor. Cada contenedor princpal requiere su propio AMS y DF.


Figura 3. Red de Agentes de dos plataformas

(Tomada de JADE Tutorial: Jade Programming for Beginners-CSELT)



Programación de Agentes


A continuación se explicará como construir un agente simple, uno que emita mensajes y otro que los reciba. La estructura de los agentes esta basado en el Tutorial Jade Primer de la Universidad de Montreal, el cual puede consultarse de forma gratuita en la dirección electrónica http://www.iro.umontreal.ca/~vaucher/Agents/Jade/JadePrimer.html


Nota: Cada uno de los programas contiene comentarios después de los caracteres ' // ' que explican alguna sección del código .

Agente Mínimo


La estructura mínima de un agente en JADE es la siguiente:

  1. import jade.core.Agent; / //importa la clase Agent
  2. public class MyAgent extends Agent //crea la clase MyAgent extendiendola de la calse Agent
  3. { protected void setup() //este el el método principal y es equivalente a main
  4. { System.out.println("Hello World. "); // imprime en pantalla
  5. // obiene su identificador local y lo imprime
  6. System.out.println("My name is "+ getLocalName());
  7. try{//mi codigo }catch(Exception e){}//aqui se puede agregar código
  8. }//termina setup
  9. }//termina clase

 

Para ejecutar este agente con el nombre a1 se utiliza la instrucción %java jade.Boot a1:MyAgent

en una ventana de sistema.


Comportamientos


Los comportmientos (Behaviours) son métodos que permiten realizar acciones en hilos de ejecución. Dan soporte al agente para realizar varias tareas y establecer los tiempos de ejecución de cada una. Son útiles para atender peticiones de forma ordenada. Por ejemplo recibiendo mensajes de un solo emisor. Jade proporciona comportamientos de tipo simple, cíclico, de recepción y envío de mensajes y los que ejecutan tareas al despertar de un bloqueo o porciones de código en segmentos de tiempo.


El comportamiento mas fácil de usar es CyclicBehaviour pues ejecuta una tarea de forma cíclica, deteniendola algunos segundos si asi se le indica. El segmento de código para ejecutar un comportamiento cícliclo se muestra a continuación.


  1. addBehaviour(new CyclicBehaviour(this){ //agrega un comportamiento de tipo cíclico

  2. public void action() { //aqui inicia la acción

  3. System.out.println(“tarea1”); //imprime una cadena

  4. ..... //aqui se puede agregar código de la tarea a realizar

  5. block(1000);} }); //detiene la ejecución del comportamiento unos //milisegundos y luego vuelve a iniciar

En este caso la accion asociada al comportamiento imprimirá la linea 'tarea1' cada segundo (block recibe el tiempo de bloqueo en milisegundos).

Nota: El setup es la inicialización del agente. Los comportamientos se ejecutan en el orden en que aparecen en el setup.
Por tanto, un loop infinito
en el setup antes de un comportamiento impedirá que este ultimo se ejecute.


Mensajes


Para construir un mensaje se utiliza la clase ACLMessage. Al construir el mensaje se debe especificar el tipo de mensaje, el contenido y el agente al que va dirigido. Algunos de los tipos de mensaje que tiene implementada la clase ACLMessage son :

ACCEPT_PROPOSAL,AGREE, CANCEL,CFP, CONFIRM, DISCONFIRM,FAILURE,INFORM, INFORM_IF,INFORM_REF,NOT_UNDERSTOOD,PROPOSE,QUERY_IF,QUERY_REF, REFUSE,REJECT_PROPOSAL y REQUEST entre ortras.


A continuación se muestra un ejemplo de codificación de un mensaje dirigido a un agente con identificador 'a1':


  1. ACLMessage msg = new ACLMessage(ACLMessage.INFORM); //tipo de mensaje

  2. msg.setContent( "Hola agente a1" ); //contenido

  3. msg.addReceiver( new AID( "a1", AID.ISLOCALNAME) ); //destinatario

  4. send(msg); //instrucción de envío


El mensaje puede ser enviado a varios destinatarios agregando instrucciones similares a la contenida en la línea 3, cambiando 'a1' por cada uno de los IDs de los agentes receptores.


Agente Emisor


Para construir un agente que envie mensajes usaremos la clase Emisor como se muestra a continuación.

  1. /*Clase Emisor
  2. *Emite un mensaje a un agente con nombre a1 */
  3. import jade.core.Agent; //importa la clase Agent
  4. import jade.core.AID; //importa los metodos para identificación de agentes
  5. import jade.lang.acl.*; //importa lenguaje
  6. public class Emisor extends Agent //crea la clase Emisor extendiendola de Agent
  7. {
  8. protected void setup() //metodo principal
  9. {
  10. //Construye mensaje de tipo INFORM
  11. ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
  12. //agrega contenido
  13. msg.setContent( "Hola!!! como estas a1?" );
  14. //agrega la direccion del destinatario
  15. msg.addReceiver( new AID( "a1", AID.ISLOCALNAME) );
  16. //envia mensaje
  17. send(msg);
  18. }//termina setup
  19. }//fin de clase

Este agente envia un mensaje a un agente con identificador 'a1'. El mensaje es de tipo informe y contiene una cadena con contenido “Hola como estas a1?”.



Agente Receptor


Para construir un agente que reciba mensajes y de respuesta a una peticion usaremos la clase Receptor como sigue.

  1. /*Clase Receptor
  2. *Captura mensajes de forma
  3. *ciclica y los responde.*/
  4. import jade.core.Agent; //importa la clase Agent
  5. import jade.core.AID; //importa los metodos para identificación de agentes
  6. import jade.core.behaviours.*; //importa comportamientos
  7. import jade.lang.acl.*; //importa lenguaje
  8. public class Receptor extends Agent //crea la clase Receptor extendiendola de Agent
  9. { protected void setup() //metodo principal
  10. {
  11. addBehaviour(new CyclicBehaviour(this){ //agrega un comportamiento ciclico
  12. public void action() {//captura mensajes de forma ciclica
  13. ACLMessage msg = receive(); //captura un mensaje de la bandeja de entrada
  14. if (msg!=null) {//si hay un mensaje
  15. System.out.println(msg.getContent());//imprime el contenido
  16. ACLMessage reply = msg.createReply();//crea una respuesta usando el remitente
  17. reply.setPerformative( ACLMessage.INFORM );//define el tipo de respuesta ACL
  18. System.out.println("bien, gracias..."); //imprime respuesta
  19. reply.setContent("bien, gracias...");//agrega contenido a la respuesta
  20. send(reply);//envia la respuesta al remitente
  21. }
  22. block();}//termina acción
  23. });//termina comportamiento
  24. }//termina setup
  25. }//fin de clase

En este caso, el agente permanece atento a cualquier petición utilizando un comportamiento cíclico. Si recibe un mensaje lo imprime. Captura la dirección del remitente para construir una respuesta. Establece el tipo y contenido de la respuesta y la envia.


Para visualizar la interacción entre los agentes Emisor y Receptor, se utiliza la instrucción

%java jade.Boot a1:Receptor a2:Emisor


Agente EmisorReceptor


Al utilizar los programas anteriores puede observarse que la clase Emisor no tiene implementado un receptor de mensajes. Para capturar la respuesta de a1 debe agregarse un comportamiento cíclico similar al de Receptor en la clase Emisor. El resultado es el siguiente.

  1. /*Clase EmisorReceptor
  2. *Emite mensajes continuamente
  3. *a los agentes a1 y a2
  4. *y recibe sus respuestas
  5. *Para ejecutar usar la instrucción
  6. *%java jade.Boot a1:EmisorReceptor a2:EmisorReceptor */
  7. import jade.core.Agent; //importa la clase Agent
  8. import jade.core.AID; //importa los metodos para identificación de agentes
  9. import jade.core.behaviours.*;//importa comportamientos
  10. import jade.lang.acl.*;//importa lenguaje
  11. public class EmisorReceptor extends Agent //crea la clase extendiendola de Agent
  12. {
  13. protected void setup() //metodo principal
  14. {
  15. addBehaviour(new CyclicBehaviour(this){ //agrega un comportamiento ciclico
  16. public void action() {//envia mensajes de forma ciclica
  17. //Construye mensaje de tipo INFORM
  18. ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
  19. //agrega contenido
  20. msg.setContent( getLocalName()+ "->Hola!!! como estas?" );
  21. //agrega la direccion del destinatario
  22. msg.addReceiver( new AID( "a1", AID.ISLOCALNAME) );
  23. msg.addReceiver( new AID( "a2", AID.ISLOCALNAME) );
  24. //envia mensaje
  25. send(msg);
  26. block(500);}//termina acción y espera 500ms
  27. //antes de volver a enviar el mensaje
  28. });//termina comportamiento
  29. addBehaviour(new CyclicBehaviour(this){ //agrega un comportamiento ciclico
  30. public void action() {//captura mensajes de forma ciclica
  31. ACLMessage msg = receive(); //captura un mensaje de la bandeja de entrada
  32. if (msg!=null) {//si hay un mensaje
  33. System.out.println(msg.getContent());//imprime el contenido
  34. ACLMessage reply = msg.createReply();//crea una respuesta usando el remitente
  35. reply.setPerformative( ACLMessage.INFORM );//define el tipo de respuesta ACL
  36. reply.setContent(getLocalName()+"bien, gracias...");
  37. send(reply);//envia la respuesta al remitente
  38. }
  39. block();}//termina acción
  40. });//termina comportamiento
  41. }//termina setup
  42. }//fin de clase

Envio de Objetos

Para enviar mensajes con varios datos en forma ordenada, es mejor enviar un objeto que una cadena. Para esto se utiliza el método setContentObject y getContentObject. El uso de estos métodos reemplazará el contenido de setContent. Por tanto es necesario el uso de los tipos de mensaje para identificar el contenido.

Un mensaje con un objeto como contenido se construye como sigue.

1. //Construye mensaje de tipo INFORM
2. ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
3. //agrega un integer como contenido
4. try{
5. Integer d=new Integer(245);
6. msg.setContentObject(d);
7. }catch(Exception e){}
8. //agrega la direccion del destinatario
9. msg.addReceiver( new AID( "a1", AID.ISLOCALNAME) );
10. //envia mensaje
11. send(msg);


El código del agente que envia mensajes con un objeto como contenido se muestra a continuación.

1./*Clase EmisorReceptor2
2. *Envia y recibe objetos continuamente
3. *Para ejecutar utilza la instrucción
4. *%java jade.Boot a1:EmisorReceptor2 a2:EmisorReceptor2
5. */
6.import jade.core.Agent; //importa la clase Agent
7.import jade.core.AID; //importa los metodos para identificación de agentes
8.import jade.core.behaviours.*;//importa comportamientos
9.import jade.lang.acl.*;//importa lenguaje
10.import java.util.*;
11.
12.public class EmisorReceptor2 extends Agent //crea la clase extendiendola de Agent
13.{
14.
15. protected void setup() //metodo principal
16. {
17. addBehaviour(new CyclicBehaviour(this){//agrega un comportamiento ciclico
18. public void action() {//envia mensajes de forma ciclica
19. //Construye mensaje de tipo INFORM
20. ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
21. //agrega un integer como contenido
22. try{
23. Integer d=new Integer(245);
24. msg.setContentObject(d);
25. }catch(Exception e){}
26. //agrega la direccion del destinatario
27. msg.addReceiver( new AID( "a1", AID.ISLOCALNAME) );
28. msg.addReceiver( new AID( "a2", AID.ISLOCALNAME) );
29. //envia mensaje
30. send(msg);
31. block(5000);}//termina acción y espera 5 seg
32. //antes de volver a enviar el mensaje
33. });//termina comportamiento
34.
35. addBehaviour(new CyclicBehaviour(this){ //agrega un comportamiento ciclico
36. public void action() {//captura mensajes de forma ciclica
37. ACLMessage msg = receive(); //captura un mensaje
38. if (msg!=null) {//si hay un mensaje
39. try{//extrae el objeto
40. Integer d=(Integer)msg.getContentObject();
41. System.out.println(getLocalName()+"recibi "+d.toString());}
42. catch(Exception e){}
43. }
44. block();}//termina acción
45. });//termina comportamiento
46.
47. }//termina setup
48.}//fin de clase



Referencias


1
Hosted by www.Geocities.ws