Agentes con JADE - III

Jade también nos proporciona un sistema de comunicación entre agentes. Podemos utilizar este sistema para hacer que los agentes interactúen entre ellos, pudiendo recrear así comportamientos más complejos.

En este minitutorial, uno más de la serie que vengo publicando, explicaré cómo utilizar dicho sistema.

Lo primero que querremos hacer a la hora de enviar un mensaje a otro agente es encontrar a dicho agente. Para ello Jade provee un sistema de páginas amarillas, el DFService. Los agentes que proveen servicios a otros agentes se registran en este directorio, de esta manera cualquier agente puede encontrar a otro agente que le provea de un servicio determinado.

Por ejemplo, para registrarse en el DF hay que escribir un código similar al que sigue, normalmente en la inicialización del agente. Todos los códigos de este tutorial se suponen que pertenecen a un agente, con lo que this referencia a un objeto de tipo Agent (en el caso de que fuera un comportamiento habría que sustituir this por myAgent).

DFAgentDescription dfd = new DFAgentDescription();
dfd.setName(this.getAID());
ServiceDescription sd = new ServiceDescription();
sd.setType("vende-pizza");
sd.setName(this.getName());
dfd.addServices(sd);
// Generar tantos ServiceDescription como servicios
// provea el agente y añadirlos al DFAgentDescription
try {
     DFService.register(agt, dfd);
} catch (FIPAException e) {
     e.printStackTrace();
}

Una vez que el agente se ha registrado puede ser encontrado por otros agentes que busquen los servicios que provea, en este caso podría encontrársele con un código como el que sigue:

DFAgentDescription dfd = new DFAgentDescription();
ServiceDescription sd;
sd = new ServiceDescription();
sd.setType("vende-pizza");
dfd.addServices(sd);
// Añadir más ServiceDescription si se busca un agente
// que provea más de un servicio
DFAgentDescription[] result;
try {
     result = DFService.search(this, dfd);
} catch (FIPAException e) {
     e.printStackTrace();
}

En result obtendremos las descripciones de los agentes que proveen los servicios que hemos buscado. Las instancias de DFAgentDescription tienen un método getName() que nos devuelve el AID, o identificador, del agente. Necesitaremos dicho identificador para mandarle un mensaje. En caso de que tuviésemos ya el identificador no es necesario buscar al agente. La manera de enviar mensajes es la siguiente:

int perf = ACLMessage.REQUEST;
// Hay muchas más performativas
// Jade sigue el estándar de la FIPA
// http://www.fipa.org/specs/fipa00037/SC00037J.html#_Toc26729689
ACLMessage msg = new ACLMessage(perf);
AID receiver = result[0].getName();
msg.addReceiver(receiver);
// Se pueden añadir tantos destinatarios como se quiera
msg.setConversationId("pedir-pizza");
// Los conversationId sirven para filtrar mensajes (siguiente ejemplo)
msg.setContent("Barbacoa familiar");
// También pueden mandarse objetos, usando el método:
// msg.setContentObject((Serializable) obj);
msg.setReplyWith(Long.toString(System.currentTimeMillis()));
// Sirve para que podamos filtrar la respuesta
this.send(msg);
MessageTemplate mt = MessageTemplate.MatchInReplyTo(msg.getReplyWith());
// Obtenemos una plantilla para filtrar, más adelante, la respuesta

Recibir mensajes es aún más fácil que mandarlos. Basta con llamar a receive(), pero suele ocurrir que necesitemos filtrar. A un agente pueden llegarle muchos mensajes, y querremos procesarlos con el comportamiento adecuado.

Lo habitual es utilizar comportamientos del tipo CyclicBehaviour para la recepción de mensajes, pues funcionan un poco como servidores. También es habitual filtrar los mensajes que procesa el comportamiento, y para eso se utilizan plantillas. El código del action() del comportamiento sería:

MessageTemplate mt = MessageTemplate.MatchConversationId("pedir-pizza");
// Hay muchos tipos de plantillas y se pueden combinar
// http://programacionjade.wikispaces.com/Comunicación#Seleccion
ACLMessage msg = myAgent.receive(mt);
if (msg != null) {
   String pedido = msg.getContent();
   String ticket = procesaPedido(pedido);
   // La creación y envío de una respuesta es opcional
   ACLMessage reply = msg.createReply();
   reply.setPerformative(ACLMessage.AGREE);
   reply.setContent(ticket);
   myAgent.send(reply);
} else {
   block();
}

Existe otra manera de buscar agentes, en vez de por servicios, por nombre. La encontraréis explicada en esta wiki.

Show Comments