Sei sulla pagina 1di 55

3.

1 Fundamentos La comunicacin entre agentes es fundamental para poder conseguir la potencia propia de los sistemas multiagente Determina el comportamiento social de los agentes Para que los agentes se puedan comunicar deben usar el mismo lenguaje de comunicacin Un lenguaje de comunicacin define los tipos de mensaje: informar, solicitar, preguntar Las conversaciones entre agentes se rigen por una serie de protocolos de interaccin El lenguaje de comunicacin de agentes (ACL) permitir transmitir una serie de conocimiento que vendr expresado en un lenguaje de contenido. Los trminos del lenguaje de contenido que representen conocimiento pertenecern a un vocabulario comn a los distintos agentes que se llama ontologa. En el caso de JADE el lenguaje de comunicacin entre agentes es FIPA-ACL. Un mensaje FIPA-ACL puede contener los siguientes campos: performative: tipo de acto comunicativo (accin que realiza el mensaje). Es el nico campo obligatorio y puede tomar uno de los siguientes valores: accept-proposal: aceptar una propuesta recibida previamente agree: estar de acuerdo en realizar alguna accin cancel: cancelar alguna accin pedida previamente cfp: solicitar propuestas para realizar una accin dada confirm: informar a un receptor que una proposicin es cierta disconfirm: informar a un receptor que una proposicin es falsa failure: informar a otro agente que se intent una accin pero fall inform: informar a un receptor que una proposicin es cierta inform-if: si el agente que recibe la accin cree que la sentencia es verdadera informar de manera afirmativa, sino indicar que es falsa. inform-ref: permite que el emisor informe al receptor de un objeto que cree que corresponde a un descriptor, como puede ser un nombre u otra descripcin que lo identifique. not-understood: informar a un receptor que el emisor no entendi el mensaje propagate: el receptor trata el mensaje como si fuese dirigido directamente a l, y debe identificar los agentes en este descriptor y enviarles el mensaje a ellos propose: enviar una propuesta para realizar una cierta accin proxy: el receptor debe seleccionar agentes objetivo denotados por una descripcin dada, y enviarles un mensaje embebido query-if: preguntarle a otro agente si una determinada proposicin es cierta query-ref: preguntar a otro agente por el objeto referenciado en una expresin refuse: rechazar realizar una accin reject-proposal: rechazar una propuesta durante una negociacin request: solicitar a un receptor que realice alguna accin request-when: solicitar al receptor que realice alguna accin cuando una proposicin dada sea cierta request-whenever: solicitar al receptor que realice alguna accin cada vez que una proposicin dada sea cierta subscribe: una intencin persistente de notificar al emisor de un determinado valor, y volver a notificarle cada vez que dicho valor cambie sender: AID del emisor

receiver: lista de AIDs de los receptores reply-to: receptor de un mensaje reply content: contenido del mensaje language: lenguaje en que se expresa el contenido encoding: codificacin del contenido ontology: ontologa usada para dar significado a los trminos del contenido protocol: identificador del protocolo de interaccin conversation-id: identificador de la conversacin. Esto es especialmente til cuando un agente mantiene varias conversaciones a la vez. reply-with: indica una expresin que tendr que ser usada por el agente que responda a dicho mensaje. Si un agente enva un mensaje que contiene :reply-with query1 el receptor responder con otro que contenga :in-reply-to query1 in-reply-to: Hace referencia a que este mensaje es una respuesta a otro anterior. reply-by: Indica el tiempo en que el mensaje ha de ser respondido. 3.2 Envo/recepcin de mensajes El intercambio de mensajes entre agentes en JADE se realiza mediante mensajes FIPAACL Mecanismo: paso asncrono de mensajes Cada agente tiene una cola de mensajes entrantes La lectura efectiva de los mensajes es a voluntad del agente Un agente puede: Leer el primer mensaje en la cola Leer el primer mensaje que satisfaga un requisito La cola de mensajes es nica para cada agente y, por lo tanto, es compartida por todos los comportamientos Cada vez que se coloca un mensaje en la cola el agente receptor es avisado Un comportamiento puede ser bloqueado en espera de la recepcin de un mensaje: sincronizacin Los mensajes intercambiados por agentes son instancias de la clase jade.lang.acl.ACLMessage

Mtodos de ACLMessage A continuacin se muestran algunos de los mtodos ms importantes de la clase ACLMessage. Para consultar ms detenidamente todos los mtodos de dicha clase se puede consultar su documentacin en la API de JADE ( ACLMessage ) setPerformative(int ): toma como parmetro una constante representativa de un tipo de accin performativa y la establece como performativa del mensaje. Los posibles actos comunicativos son los que hemos visto antes y las constantes que los representan se pueden ver en la API. Por ejemplo, para hacer que el mensaje msg sea de tipo agree bastar con escribir: msg.setPerformative(ACLMessage.AGREE); getPerformative(): devuelve un entero equivalente a la constante que representa a la performativa del mensaje createReply(): crea un mensaje de respuesta para el mensaje sobre el que es aplicado, poniendo los valores oportunos en campos como receiver, conversation-id, etc. addReceiver(AID ): toma como parmetro un AID y lo aade a la lista de receptores getAllReceiver(): devuelve un iterador sobre la lista de receptores. setContent(String ): recibe como parmetro una cadena y la pone como contenido del mensaje getContent(): devuelve una cadena con el contenido del mensaje El resto de mtodos get/set son similares, simplemente vara el tipo del valor introducido o devuelto. Por ejemplo, getSender() devolver un AID mientras que getLanguage() devolver una cadena. La performativa puede indicarse directamente pasando el valor al constructor de ACLMessage, lo cul es recomendable porque todos los mensajes deben contener al menos la performativa. Enviar un mensaje

- Pasos: Crear un objeto ACLMessage Usar los mtodos de ACLMessage para rellenar los campos necesarios Llamar al mtodo send() de la clase Agent. El mtodo send() recibe como parmetro un ACLMessage, aade el valor oportuno al campo sender (remitente) y enva el mensaje a los destinatarios - Ejemplo: ACLMessage mensaje = new ACLMessage(ACLMessage.INFORM); mensaje.setLanguage("Espaol"); mensaje.addReceiver(id); mensaje.setContent("Hola Receptor"); send(mensaje); Mensaje enviado: (INFORM :sender ( agent-identifier :name emisor@luna:1099/JADE :addresses (sequence http://luna:7778/acc )) :receiver (set ( agent-identifier :name receptor@luna:1099/JADE ) ) :content "Hola Receptor" :language Espaol )

Recibir un mensaje Se usar el mtodo receive() de la clase Agent. El mtodo receive() obtiene el primer mensaje de la cola de mensajes y lo devuelve (devuelve null si la cola est vaca). El mesaje recibido es exactamente igual al anterior. ACLMessage mensaje = receive(); Ejemplo de intercambio de mensajes entre dos agentes: Esta clase representa al agente Emisor, que es el que se encarga de emitir el mensaje "Hola que tal receptor?". package examples.practica4; import jade.core.*; import jade.core.behaviours.*; import jade.lang.acl.*; public class Emisor extends Agent { class EmisorComportaminento extends SimpleBehaviour { boolean fin = false;

public void action() { System.out.println(getLocalName() +": Preparandose para enviar un mensaje a receptor"); AID id = new AID(); id.setLocalName("receptor"); // Creacin del objeto ACLMessage ACLMessage mensaje = new ACLMessage(ACLMessage.REQUEST); //Rellenar los campos necesarios del mensaje mensaje.setSender(getAID()); mensaje.setLanguage("Espaol"); mensaje.addReceiver(id); mensaje.setContent("Hola, que tal receptor ?"); //Envia el mensaje a los destinatarios send(mensaje); System.out.println(getLocalName() +": Enviando hola a receptor"); System.out.println(mensaje.toString()); fin = true; } public boolean done() { return fin; } } protected void setup() { addBehaviour(new EmisorComportaminento()); } } Y esta otra representa al agente Receptor que recibe el mensaje del agente Emisor. package examples.practica4; import jade.core.*; import jade.core.behaviours.*; import jade.lang.acl.ACLMessage; public class Receptor extends Agent { class ReceptorComportaminento extends SimpleBehaviour { private boolean fin = false; public void action() {

System.out.println(" Preparandose para recibir"); //Obtiene el primer mensaje de la cola de mensajes ACLMessage mensaje = receive(); if (mensaje!= null) { System.out.println(getLocalName() + ": acaba de recibir el siguiente mensaje: "); System.out.println(mensaje.toString()); fin = true; } } public boolean done() { return fin; } } protected void setup() { addBehaviour(new ReceptorComportaminento()); } } - En la plataforma JADE lanzamos: Un agente de la clase Receptor llamndolo con el nombre receptor (java jade.Boot -container receptor:examples.practica4.Receptor). Un agente de la clase Emisor llamndolo con el nombre "emisor1" (java jade.Boot -container emisor1:examples.practica4.Emisor). - Obtenemos la siguiente salida: emisor1: Preparandose para enviar un mensaje a receptor emisor1: Enviando hola a receptor receptor: acaba de recibir el siguiente mensaje: (REQUEST :sender ( agent-identifier :name emisor1@luna:1099/JADE :addresses (sequence http://luna:7778/acc )) :receiver (set ( agent-identifier :name receptor@luna:1099/JADE ) ) :content "Hola, que tal receptor ?" :language Espaol ) Nota importante: Si hubisemos lanzado primero el emisor no se habra obtenido ninguna salida porque al no estar registrado el receptor del mensaje en el AMS, este enviara un mensaje FAILURE al agente emisor. Problema: si el Receptor no recibe ningn mensaje, ste est ejecutndose continuamente, consumiendo CPU. Posibles soluciones:

Solucin: Usar el mtodo block() de la clase Behaviour: public void action() { ACLMessage mensaje = receive(); if (mensaje != null) { ... }else { System.out.println("Receptor: Esperando a recibir mensaje..."); block(); } } Por lo tanto la clase Receptor quedara as: package examples.practica4; import jade.core.*; import jade.core.behaviours.*; import jade.lang.acl.ACLMessage; public class Receptor extends Agent { class ReceptorComportaminento extends SimpleBehaviour { private boolean fin = false; public void action() { System.out.println(" Preparandose para recibir"); //Obtiene el primer mensaje de la cola de mensajes ACLMessage mensaje = receive(); if (mensaje!= null) { System.out.println(getLocalName() + ": acaba de recibir el siguiente mensaje: "); System.out.println(mensaje.toString()); fin = true; }else{ System.out.println("Receptor: Esperando a recibir mensaje..."); block(); } } public boolean done() { return fin; } } protected void setup() {

addBehaviour(new ReceptorComportaminento()); } } Solucin: Usar el mtodo blockingReceive() de Agent en lugar del mtodo receive(): public void action() { ACLMessage mensaje = blockingReceive(); if (mensaje != null) { ... } } Por lo tanto la clase Receptor quedara as: package examples.practica4; import jade.core.*; import jade.core.behaviours.*; import jade.lang.acl.ACLMessage; public class Receptor extends Agent { class ReceptorComportaminento extends SimpleBehaviour { private boolean fin = false; public void action() { System.out.println(" Preparandose para recibir"); //Obtiene el primer mensaje de la cola de mensajes ACLMessage mensaje = blockingReceive(); if (mensaje!= null) { System.out.println(getLocalName() + ": acaba de recibir el siguiente mensaje: "); System.out.println(mensaje.toString()); fin = true; } } public boolean done() { return fin; } } protected void setup() { addBehaviour(new ReceptorComportaminento()); } }

Diferencia entre las dos soluciones: block(): solo bloquea un comportamiento del agente hasta que llegue un mensaje, el bloqueo no se produce hasta que termina el comportamiento sobre el que se aplica. blockingReceive(): bloquea instantneamente todos los comportamientos del agente hasta que llegue un mensaje, adems devuelve el mensaje recibido que liber el bloqueo. Responder a mensajes: Se puede hacer de dos formas: Indicando como receptor al emisor del mensaje anterior. De esta manera, la clase Emisor quedara as: package examples.practica4; import jade.core.*; import jade.core.behaviours.*; import jade.lang.acl.*; public class Emisor extends Agent { class EmisorComportaminento extends SimpleBehaviour { boolean fin = false; public void action() { System.out.println(getLocalName() +": Preparandose para enviar un mensaje a receptor"); AID id = new AID(); id.setLocalName("receptor"); // Creacin del objeto ACLMessage ACLMessage mensaje = new ACLMessage(ACLMessage.REQUEST); //Rellenar los campos necesarios del mensaje mensaje.setSender(getAID()); mensaje.setLanguage("Espaol"); mensaje.addReceiver(id); mensaje.setContent("Hola, que tal receptor ?"); //Envia el mensaje a los destinatarios send(mensaje); System.out.println(getLocalName() +": Enviando hola a receptor"); System.out.println(mensaje.toString()); //Espera la respuesta ACLMessage mensaje2 = blockingReceive(); if (mensaje2!= null) {

System.out.println(getLocalName() + ": acaba de recibir el siguiente mensaje: "); System.out.println(mensaje2.toString()); fin = true; } } public boolean done() { return fin; } } protected void setup() { addBehaviour(new EmisorComportaminento()); } } Y el de la clase Receptor asi: package examples.practica4; import jade.core.*; import jade.core.behaviours.*; import jade.lang.acl.ACLMessage; public class Receptor extends Agent { class ReceptorComportaminento extends SimpleBehaviour { private boolean fin = false; public void action() { System.out.println(" Preparandose para recibir"); //Obtiene el primer mensaje de la cola de mensajes ACLMessage mensaje = receive(); if (mensaje!= null) { System.out.println(getLocalName() + ": acaba de recibir el siguiente mensaje: "); System.out.println(mensaje.toString()); // Envia constestacin System.out.println(getLocalName() +": Enviando contestacion"); ACLMessage respuesta = new ACLMessage( ACLMessage.INFORM ); respuesta.setContent( "Bien" ); respuesta.addReceiver( mensaje.getSender() ); send(respuesta); System.out.println(getLocalName() +": Enviando Bien a receptor"); System.out.println(respuesta.toString());

fin = true; } } public boolean done() { return fin; } } protected void setup() { addBehaviour(new ReceptorComportaminento()); } } Haciendo uso de createReply(). De esta manera, la clase Receptor quedara as: package examples.practica4; import jade.core.*; import jade.core.behaviours.*; import jade.lang.acl.ACLMessage; public class Receptor extends Agent { class ReceptorComportaminento extends SimpleBehaviour { private boolean fin = false; public void action() { System.out.println(" Preparandose para recibir"); //Obtiene el primer mensaje de la cola de mensajes ACLMessage mensaje = receive(); if (mensaje!= null) { System.out.println(getLocalName() + ": acaba de recibir el siguiente mensaje: "); System.out.println(mensaje.toString()); // Envia constestacin System.out.println(getLocalName() +": Enviando contestacion"); ACLMessage respuesta = mensaje.createReply(); respuesta.setPerformative( ACLMessage.INFORM ); respuesta.setContent( "Bien" ); send(respuesta); System.out.println(getLocalName() +": Enviando Bien a receptor"); System.out.println(respuesta.toString()); fin = true; } }

public boolean done() { return fin; } } protected void setup() { addBehaviour(new ReceptorComportaminento()); } } Y el de la clase Emisor no vara con respecto al anterior ejemplo. 3.3 Seleccin de mensajes Para seleccionar los mensajes que un agente desea recibir podemos utilizar la clase MessageTemplate. Esta clase permite definir filtros para cada atributo del mensaje ACLMessage y se utiliza como parmetro en los mtodos receive y blockingReceive. En esta clase se definen un conjunto de mtodos estticos que nos devuelven como resultado un objeto de tipo MessageTemplate. Las diferentes opciones de filtrado son: MatchPerformative( performative ) donde performative puede ser: ACLMessage.INFORM ACLMessage.PROPOSE ACLMessage.QUERY_REF ... MatchSender( AID ) MatchConversationID( String ): Permite dedicar un comportamiento a gestionar una conversacin/negociacin. and( Template1, Template2 ): realiza un and lgico entre los dos filtros. or ( Template1, Template2 ): realiza un or lgico entre los dos filtros. not( Template ): invierte el filtro. MatchOntology( String ): devuelve un filtro segn el nombre de la ontologia que le pasemos como parmetro. MatchProtocol( String ): devuelve un filtro segn el nombre del protocolo que le pasamos. MatchLanguage( String ): devuelve un filtro segn el lenguaje introducido. MatchContent( String ): crea una plantilla segn el contenido del mensaje. MatchReplyWith( String ): devuelve un filtro segn el campo replywith. Adems existe el mtodo match(ACLMessage) que devuelve verdadero si el mensaje que le pasamos como parmetro cumple el filtro definido en el objeto MessageTemplate. En el ejemplo anterior, el agente Receptor podra solo estar interesado en recibir mensajes del tipo REQUEST, en Espaol y procedentes exclusivamente del agente "emisor". Esto se puede obtener modificando el comportamiento:

package examples.practica4; import jade.core.*; import jade.core.behaviours.*; import jade.lang.acl.ACLMessage; import jade.lang.acl.MessageTemplate; public class FiltroReceptor extends Agent { class Comportamiento extends SimpleBehaviour { boolean fin = false; MessageTemplate plantilla = null; public Comportamiento () { AID emisor = new AID(); emisor.setLocalName("emisor"); //Devuelve una plantilla de mensaje que coincida con algn mensaje con un slot :sender dado. MessageTemplate filtroEmisor = MessageTemplate.MatchSender(emisor); //Devuelve una plantilla de mensaje que coincida con algn mensaje con una perfomativa dada. MessageTemplate filtroInform = MessageTemplate.MatchPerformative(ACLMessage.REQUEST); //Devuelve una plantilla de mensaje que conicida con algn mensaje con una slot :language dado MessageTemplate filtroIdioma = MessageTemplate.MatchLanguage("Espaol"); //Operacin lgica AND entre dos objetos de esta clase. plantilla = MessageTemplate.and(filtroInform,filtroEmisor); plantilla = MessageTemplate.and(plantilla,filtroIdioma); } public void action() { ACLMessage mensaje = receive(plantilla); if (mensaje!= null) { System.out.println(getLocalName() + ": ha recibido el siguiente mensaje: "); System.out.println(mensaje.toString()); fin = true; }else { System.out.println(getLocalName() + ":Esperando mensajes..."); block(); }

} public boolean done() { return fin; } } protected void setup() { addBehaviour(new Comportamiento()); } }

3.4 Pginas amarillas (DF Agent) Permite a los agentes publicar los servicios que proporcionan, para que otros agentes puedan acceder a ellos.

Los agentes interactan con el DF intercambiando mensajes ACL usando el lenguaje de SL0 y la ontologa FIPA-agent-management. Jade nos facilita esta tarea mediante los mtodos implementados en la clase DFService . Publicar servicios: El agente debe proporcionar al DF una descripcin, incluyendo su AID, los protocolos, lenguajes y ontologas que el resto de agentes necesitan conocer para interactuar con l; y la lista de servicios publicados. Para cada servicio se proporciona una descripcin, incluyendo: tipo de servicio, nombre, protocolos, lenguajes y ontologas; y una serie de propiedades especficas del servicio. Antes de finalizar su ejecucin el agente debe eliminar del DF sus servicios. Para realizar las acciones anteriores Jade proporciona los siguientes mtodos: static DFAgentDescription register: registra los servicios de un agente en el DF. static void deregister: elimina del registro del DF los servicios del agente. Los servicios se definen con los siguientes mtodos de la clase ServiceDescription: void setName: modifica el nombre del servicio. void setOwnership: modifica el propietario del servicio. void setType: modifica el tipo de servicio. void addLanguages: aade lenguaje del servicio. void addOntologies: aade ontologa del servicio. void addProtocols: aade protocolo del servicio. void addProperties: aade propiedades del servicio. La descripcion del agente se modifica con los siguientes mtodos de la clase DFAgentDescription:

void setName: modifica el AID de la descripcin del agente. void addServices: aade el servicio pasado por parmetro a la descripcin del agente. void removeServices: elimina el servicio pasado por parmetro a la descripcin del agente. void addLanguages: aade lenguajes que el agente entiende. void addOntologies: aade ontologas que el agente entiende. void addProtocols: aade protocolos que el agente entiende. En el siguiente ejemplo, habr dos agentes que ofrecen servicio y uno que los solicita. Esta es la clase Ofrece que representa a uno de los agentes que ofrece servicios: package examples.practica4; import jade.core.Agent; import jade.core.AID; import jade.domain.DFService; import jade.domain.FIPAAgentManagement.*; import jade.domain.FIPAException; public class Ofrece extends Agent { protected void setup() { // Descripcin del agente DFAgentDescription descripcion = new DFAgentDescription(); descripcion.setName(getAID()); descripcion.addLanguages("Castellano"); // Descripcion de un servicio se proporciona ServiceDescription servicio = new ServiceDescription(); servicio.setType("Tipo del servicio 1"); servicio.setName("Nombre del servicio 1"); // Aade dicho servicio a la lista de servicios de la descripcin del agente descripcion.addServices(servicio); // Descripcion de otro servicio se proporciona servicio = new ServiceDescription(); servicio.setType("Tipo del servicio 2"); servicio.setName("Nombre del servicio 2"); // Aade dicho servicio a la lista de servicios de la descripcin del agente descripcion.addServices(servicio); try { DFService.register(this, descripcion); } catch (FIPAException e) {

e.printStackTrace(); } } protected void takeDown() { try { DFService.deregister(this); } catch (FIPAException fe) { fe.printStackTrace(); } System.out.println("El agente "+getAID().getName()+" ya no ofrece sus servicios."); } } Esta es la clase Ofrece2 que representa al segundo agente que ofrece servicios: package examples.practica4; import jade.core.Agent; import jade.core.AID; import jade.domain.DFService; import jade.domain.FIPAAgentManagement.*; import jade.domain.FIPAException; public class Ofrece2 extends Agent { protected void setup() { // Descripcin del agente DFAgentDescription descripcion = new DFAgentDescription(); descripcion.setName(getAID()); descripcion.addLanguages("Castellano"); // Descripcion de un servicio se proporciona ServiceDescription servicio = new ServiceDescription(); servicio.setType("Tipo del servicio 3"); servicio.setName("Nombre del servicio 3"); // Aade dicho servicio a la lista de servicios de la descripcin del agente descripcion.addServices(servicio); try { DFService.register(this, descripcion); } catch (FIPAException e)

{ e.printStackTrace(); } } protected void takeDown() { try { DFService.deregister(this); } catch (FIPAException fe) { fe.printStackTrace(); } System.out.println("El agente "+getAID().getName()+" ya no ofrece sus servicios."); } } Esta es la clase Pide que representa al agente que busca en las pginas amarillas agentes que ofrezcan los servicios que solicita: package examples.practica4; import jade.core.Agent; import jade.core.AID; import jade.domain.DFService; import jade.domain.FIPAAgentManagement.*; import java.util.Iterator; public class Pide extends Agent { protected void setup() { ServiceDescription servicio = new ServiceDescription(); servicio.setType("Tipo del servicio 1"); // Plantilla de descripcin que busca el agente DFAgentDescription descripcion = new DFAgentDescription(); descripcion.addLanguages("Castellano"); // Servicio que busca el agente descripcion.addServices(servicio); try { // Todas las descripciones que encajan con la plantilla proporcionada en el DF DFAgentDescription[] resultados = DFService.search(this,descripcion); if (resultados.length == 0) System.out.println("Ningun agente ofrece el servicio deseado");

for (int i = 0; i < resultados.length; ++i) { System.out.println("El agente "+resultados[i].getName()+" ofrece los siguientes servicios:"); Iterator servicios = resultados[i].getAllServices(); int j = 1; while(servicios.hasNext()) { servicio = (ServiceDescription)servicios.next(); System.out.println(j+"- "+servicio.getName()); System.out.println(); j++; } } } catch (Exception e) { e.printStackTrace(); } } } Busqueda de servicios: Un agente que busca servicios debe proporcionar una plantilla de descripcin de la clase DFAgentDescription. El resultado de la bsqueda es la lista de todas las descripciones que encajan con la plantilla proporcionada (los campos especificados en la plantilla estn presentes en la descripcin con los mismos valores, los campos no cubiertos no se comprueban). Para realizar las acciones anteriores jade proporciona diversos mtodos de bsqueda que se encuentran en la clase DFService. En el ejemplo anterior se ha utilizado el mtodo search(Agente, Descripcin). 3.5 Pginas blancas (AMS Agent) Garantiza que cada agente en la plataforma tenga un nico nombre. Encargado de proporcionar los servicios de pginas blancas y ciclo de vida, y de mantener el directorio de los identificadores de agentes (AID: Agent Identifier) y su estado. Cada agente debe registrarse con el AMS para obtener un AID vlido, esta operacin en JADE la realizan los agentes de manera automtica en el agente AMS por defecto. Para acceder a los servicios del agente AMS hay que importar la clase AMSService. Esta clase contiene los siguientes mtodos: static void register: registra al agente en el AMS. Tanto esta operacin como la operacin deregister se realizan automticamente en JADE cuando se ejecutan los mtodos setup() y takeDown() respectivamente, por lo tanto no suelen ser usados normalmente.

static void deregister: elimina el registro del agente en el AMS. static void modify: modifica los datos del agente en el AMS. static AMSAgentDescription[] search: devuelve la descripcin de los agentes registrados en el agente AMS. En el siguiente ejemplo un agente imprime la informacin sobre los agentes del sistema accediendo al agente AMS. package examples.practica4; import jade.core.Agent; import jade.core.AID; import jade.domain.AMSService; import jade.domain.FIPAAgentManagement.*; public class PaginasBlancas extends Agent { protected void setup() { AMSAgentDescription [] agentes = null; System.out.println("El agente " + getAID().getName() + " se ha iniciado."); try { SearchConstraints restricciones = new SearchConstraints(); restricciones.setMaxResults ( new Long(-1) ); /// Todos agentes = AMSService.search( this, new AMSAgentDescription (), restricciones ); } catch (Exception e) { System.out.println(e); } AID miId = getAID(); System.out.println(); System.out.println("Lista de agentes activos:"); for (int i=0; i < agentes.length; i++) { AID id = agentes[i].getName(); System.out.println(( id.equals( miId ) ? "--> " : " id.getName() ); } } } 3.6 Protocolos de comunicacin

" ) + "Agente" + i + ": " +

Los agentes se pueden comunicar entre s de varias formas distintas, es decir, las conversaciones que pueden llevar a cabo responden a algn patrn de los especificados por FIPA, denominados protocolos. Cada uno de estos protocolos establece el intercambio bsico de mensajes que existe entre dos agentes para un tipo de conversacin dada, ya sea una peticin, una consulta etc. Ejemplos de estos protocolos son el FIPA-Request, FIPA-Propose, FIPA-QueryPues bien, en estos protocolos de comunicacin JADE define dos roles, el que inicia la conversacin y el que es objeto de la misma (rol Initiator y rol Responder). Para la mayora de protocolos JADE proporciona unas clases de comportamiento prediseadas para ambos roles. Estas clases se encuentran en el paquete jade.proto. 3.6.1 El paquete jade.proto Este paquete agrupa todas las clases que, en forma de comportamientos, facilitan la implementacin de los protocolos de comunicacin definidos por FIPA. Dichas clases se agrupan dentro del paquete en cuatro parejas de clases principales con las cuales se podrn implementar la mayora de los protocolos. El motivo de que sean parejas es que para cada protocolo se necesita la clase Initiator y la clase Responder, que implementarn respectivamente el agente que inicie la conversacin y el que sea destinatario del primer mensaje, que puede ser un solo agente o varios. A mayores de estas cuatro clases existen otras subclases que aaden valores a las principales o que las simplifican. Cada par de clases esta indicado para implementar una serie de protocolos: Comportamientos Protocolos FIPA AchieveREInitiator AchieveREResponder SimpleAchieveREInitiator SimpleAchieveREResponder IteratedAchieveREInitiator SSIteratedAchieveREResponder FIPA-Request FIPA-Query FIPA-Recruiting FIPA-Request-When FIPA-Brokering ContractNetInitiator ContractNetResponder SSContractNetResponder FIPA-Contract-Net SubscriptionInitiator SubscriptionResponder FIPA-Subscribe FIPA-Request-Whenever ProposeInitiator ProposeResponder FIPA-Propose Como ya se indic ms arriba estas clases implementan comportamientos, y concretamente el tipo de comportamiento que implementa es el FSMBehaviour, ya que las acciones de los agentes en los protocolos FIPA se puede reducir simplemente a una

mquina de estados finitos, y este es el tipo de comportamiento indicado para representar dichas mquinas. Este comportamiento es ms fcil de comprender observando el siguiente ejemplo en el cual Pedro le pide la hora Juan: Pedro: Juan, Tienes hora? Juan: S, un segundo. Juan mira el reloj. Juan: Son las seis en punto. Esta conversacin sigue el modelo del protocolo FIPA-Request, es decir, hay una peticin del agente Initiator y una aceptacin y respuesta del agente Responder. Tambin podran darse dos casos ms a mayores: que Juan no tenga hora, o que la tenga y no se la quiera dar a Pedro. Y la mquina de estados finita que reflejara esta conversacin sera la siguiente: Diagrama de estados de los interlocutores de una conversacin. En este ejemplo los rectngulos son representan estados y las flechas eventos. En JADE los comportamientos de los iniciadores se ejecutarn una sola vez, mientras que los de los respondedores sern cclicos, por lo que volvern al estado inicial tras alcanzar el estado final. La implementacin de las clases del paquete jade.proto est hecha de tal modo que el programador se podr abstraer de tareas tales como el envo de mensajes o el cambio de estado. La principal tarea del programador ser definir qu se debe hacer en cada estado del protocolo y preparar los mensajes antes de ser enviados. La acciones que se realizan en cada estado se definen mediante los manejadores (Handlers), mientras que los mensajes se concretan mediante los preparadores (Prepares). La siguiente figura muestra dicho funcionamiento con claridad: Protocolo FIPA-Request asociado a sus manejadores y preparadores.

3.6.1.1 Manejadores (handle y registerHandler) Un manejador es un comportamiento que se iniciar al entrar en el estado al que est asociado. Existen dos formas de implementar un manejador, que explicaremos a continuacin, con un cdigo de ejemplo equivalente, que imprimir el mensaje Inform recibido cuando se cambie de estado por la llegada de un mensaje Inform: 1. Sobrecarga de mtodos handle: Cada comportamiento tiene una serie de mtodos handle con la forma: handleInform, handleRequest, etc. Cada uno de ellos ser invocado cuando se reciba el tipo de mensaje correspondiente. protected void handleInform(ACLMessage inform) { System.out.println(Inform recibido); } 2. Registrar manejadores propios: Se podrn registrar comportamientos para que acten como manejadores. El registro se har a travs de los mtodos registerHandler que

tienen la forma: registerHandleInform, registerHandleRequest, etc. En caso de registrar un comportamiento como manejador, el sistema ignorar las sobrecargas de los mtodos handler y se limitar a iniciar los comportamientos registrados. protected void setup() { ... this.registerHandleInform(new OneShotBehaviour() { public void action() { System.out.println(Inform recibido); } }); ... } Cada vez que se entre en un estado nuevo se lanzar un nuevo comportamiento que, en el caso de haber registrado uno nuevo (registerHandle) se lanzar ese mismo, pero si no, se lanzar un OneShotBehaviour que invocar al mtodo handle por defecto de la clase. Manejadores asociados a preformativas: Hay ciertos manejadores que sern iniciados cada vez que llegue un mensaje con determinada preformativa, pero siempre que ese mensaje llegue segn lo esperado por el protocolo FIPA que corresponda. Manejadores AllResponses: Sern lanzados cuando se reciban todas las respuestas al primer mensaje enviado por el iniciador o cuando se supere el tiempo de espera, indicado en el campo reply-by de ese mensaje inicial. Proporciona acceso a todos los mensajes recibidos. Se encuentra en todos los iniciadores. Manejadores AllResultNotifications: Sern lanzados cuando se reciban todas las respuestas finales o cuando se supere el tiempo de espera, indicado en el campo replyby de ese mensaje inicial. Proporciona acceso a todos los mensajes recibidos. Solamente se encuentra en el iniciador AchieveRE y en el ContractNet. Manejador OutOfSequence: Este es el manejador que se encarga de actuar en el caso de que el mensaje recibido no se corresponda con el esperado segn los protocolo FIPA. Es decir, funcionar con las excepciones. 3.6.1.2 Preparadores (prepare y registerPrepare) Un preparador lo que hace es preparar un mensaje para ser enviado, por lo que son iniciados antes de enviar un mensaje del tipo al que estn asociados. El trabajo con los preparadores es idntico al caso de los manejadores, pudiendo tambin sobrecargar los mtodos prepare o registrando comportamientos que implementen los preparadores. Los mtodos prepare devuelven el mensaje o mensajes que se van a enviar. En el caso de registrar comportamientos habr que guardar en el almacn de datos y con una clave determinada el mensaje que se desea enviar. Se deber tener mucho cuidado a la hora de rellenar los campos de los mensajes, pues el hecho de dejar vaco un campo puede interrumpir todo el protocolo. Por ello es muy recomendable hacer uso del mtodo createReply() presente en los mensajes ACLMessage. Este mtodo genera un nuevo mensaje de respuesta al original con los campos necesarios cubiertos, as tan slo habr que modificar los que correspondan.

Actualmente, gran parte de los preparadores estn obsoletos, quedando su responsabilidad en manos de los manejadores. 3.6.1.3 El almacn de datos (DataStore) El almacn de datos guarda todos los mensajes que se envan o reciben durante todo el proceso de comunicacin, es decir, a lo largo de la ejecucin de un protocolo. Cada clase define un conjunto de constantes que servirn de clave para acceder a un tipo de mensajes determinado. Estas constantes se caracterizan por emplear el sufijo KEY en su nombre. Por ejemplo, si en la clase ProposeResponser se desea registrar el mensaje de respuesta (Response) que se desea enviar, se har de la siguiente manera: ACLMessage response = new ACLMessage(ACLMessage.ACCEPT_PROPOSAL); this.getDataStore().put(ProposeResponder.RESPONSE_KEY, response); Si lo que se desea es obtener el mensaje Propose recibido, habr que hacer lo siguiente: ACLMessage propose = (ACLMessage) this.getDataStore().get(ACLMessage.PROPOSE_KEY); Hay que ser cuidadoso al utilizar el almacn de datos, ya que no funciona igual con todas las clases, por lo que sera conveniente mirar la API de cada clase. 3.6.2 AchieveRE La caracterstica principal de los mensajes en FIPA-ACL es que cada uno de ellos representa un acto comunicativo, es decir, una accin que un agente puede ejecutar. El estndar FIPA especifica para cada acto comunicativo: Precondiciones de Viabilidad (Feasibility Preconditions): Condiciones que necesariamente se deben satisfacer antes de que un agente pueda ejecutar una accin, es decir, antes de que enve un mensaje. Efecto Razonable (Rational Effect): Efecto esperado como consecuencia de la accin, en otras palabras, la razn por la que ha sido enviado el mensaje. En el cuadro de ms arriba se indicaba qu protocolos implementa el conjunto de clases AchieveRE. Para ello utiliza las clases AchieveREInitiator y AchieveREResponder, una para el rol iniciador y otra para el respondedor. Tambin estn las subclases SimpleAchieveREInitiator y SimpleAchieveREResponder, cuyas principales diferencias son que slo permite conversaciones 1:1 y que no permite al programador registrar comportamientos especficos cmo manejadores de los estados de los protocolos. Otro tipo de subclases son IteratedAchieveREInitiator y SSIteratedAchieveREResponder que implementan una versin iterativa del FIPARequest, en la que habiendo recibido todas las notificaciones de resultados de los respondedores, el iniciador puede enviar de nuevo mensajes de iniciacin. La sesin de cada protocolo con un respondedor dado terminar si: El iniciador enva al respondedor un mensaje explicito CANCEL en lugar del siguiente mensaje de iniciacin. El respondedor responde negativamente con REFUSE, NOT_UNDERSTOOD o FAILURE. El respondedor incluye una bandera de terminacin a la notificacin de resultado INFORM. Esta bandera de terminacin puede detectarse usando el mtodo isSessionTerminated().

Algunos de los protocolos que implementa la clase AchieveRE son: FIPA-Request Este protocolo permite a un agente solicitar a otro la realizacin de una accin y est identificado en el parmetro del protocolo del mensaje con el valor fipa-request. Los mensajes que se intercambian son: Request, la peticin. Agree, si acepta la peticin o refuse si la rechaza. En caso de que el mensaje anterior fuera un agree: Failure si ocurri algn error en el proceso, inform-done si se realiz correctamente e inform-result si adems se tiene que comunicar el resultado. A continuacin se presenta un ejemplo que hace uso de estas clases. En este ejemplo un agente (representado por la clase Testigo) avisar a los hospitales pasados como parmetro de que ha habido un accidente de trfico y pide ayuda. Es decir podremos crear varios hospitales y pasarlos todos como parmetros al testigo. Los hospitales (representados por la clase Hospital) podrn atender la emergencia o descartarla por estar fuera de su radio de actuacin. Para que funcione bien, hay que lanzar primero el agente Hospital (uno o varios) y luego pasarle como parmetro al agente Testigo uno o mas agentes (en caso de no pasar ninguno dar un error de falta de parmetros). Testigo package examples.practica5; import jade.core.Agent; import jade.core.AID; import jade.lang.acl.ACLMessage; import jade.proto.AchieveREInitiator; import jade.domain.FIPANames; public class Testigo extends Agent { protected void setup() { Object[] args = getArguments(); if (args != null && args.length > 0) { System.out.println("He visto un accidente! Solicitando ayuda a varios hospitales..."); ACLMessage msg = new ACLMessage(ACLMessage.REQUEST); for (int i = 0; i < args.length; ++i) msg.addReceiver(new AID((String) args[i], AID.ISLOCALNAME)); msg.setProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST); msg.setContent("accidente a 5 kms"); addBehaviour(new ManejadorInitiator(this,msg)); }

else System.out.println("Debe de esribir el nombre de un hospital como minimo (pasado como parametro)."); } class ManejadorInitiator extends AchieveREInitiator { public ManejadorInitiator(Agent a,ACLMessage msg) { super(a,msg); } protected void handleAgree(ACLMessage agree) { System.out.println("Hospital " + agree.getSender().getName() + " informa que han salido a atender el accidente."); } protected void handleRefuse(ACLMessage refuse) { System.out.println("Hospital " + refuse.getSender().getName() + " responde que el accidente esta fuera de su radio de accion. No llegaremos a tiempo!!!"); } protected void handleNotUnderstood(ACLMessage notUnderstood) { System.out.println("Hospital " + notUnderstood.getSender().getName() + " no puede entender el mensaje."); } protected void handleInform(ACLMessage inform) { System.out.println("Hospital " + inform.getSender().getName() + " informa que han atendido el accidente."); } protected void handleFailure(ACLMessage fallo) { if (fallo.getSender().equals(myAgent.getAMS())) { System.out.println("Alguna de los hospitales no existe"); } else { System.out.println("Fallo en el hospital " + fallo.getSender().getName() + ": " + fallo.getContent().substring(1, fallo.getContent().length()-1)); } } } }

Hospital package examples.practica5; import java.util.StringTokenizer; import jade.core.Agent; import jade.lang.acl.ACLMessage; import jade.lang.acl.MessageTemplate; import jade.proto.AchieveREResponder; import jade.domain.FIPANames; import jade.domain.FIPAAgentManagement.NotUnderstoodException; import jade.domain.FIPAAgentManagement.RefuseException; import jade.domain.FIPAAgentManagement.FailureException; public class Hospital extends Agent { public double DISTANCIA_MAX; protected void setup() { DISTANCIA_MAX=(Math.random()*10); System.out.println("Hospital "+getLocalName()+": Esperando avisos..."); MessageTemplate protocolo = MessageTemplate.MatchProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST); MessageTemplate performativa = MessageTemplate.MatchPerformative(ACLMessage.REQUEST); MessageTemplate plantilla = MessageTemplate.and(protocolo, performativa); addBehaviour(new ManejadorResponder(this, plantilla)); } class ManejadorResponder extends AchieveREResponder { public ManejadorResponder(Agent a,MessageTemplate mt) { super(a,mt); } protected ACLMessage handleRequest(ACLMessage request)throws NotUnderstoodException, RefuseException { System.out.println("Hospital "+getLocalName()+": Hemos recibido una llamada de " + request.getSender().getName() + " diciendo que ha visto un accidente."); StringTokenizer st=new StringTokenizer(request.getContent()); String contenido=st.nextToken(); if(contenido.equalsIgnoreCase("accidente")) { st.nextToken(); int distancia=Integer.parseInt(st.nextToken()); if (distancia<DISTANCIA_MAX) {

System.out.println("Hospital "+getLocalName()+": Vamos echando chispas!!!"); ACLMessage agree = request.createReply(); agree.setPerformative(ACLMessage.AGREE); return agree; } else { System.out.println("Hospital "+getLocalName()+": Accidente fuera de nuestro radio de accion. No llegaremos a tiempo!!!"); throw new RefuseException("Accidente demasiado lejos"); } } else throw new NotUnderstoodException("Hospital manda un mensaje que no puedo entender."); } protected ACLMessage prepareResultNotification(ACLMessage request,ACLMessage response) throws FailureException { if (Math.random() > 0.2) { System.out.println("Hospital "+getLocalName()+": Han vuelto de atender el accidente."); ACLMessage inform = request.createReply(); inform.setPerformative(ACLMessage.INFORM); return inform; } else { System.out.println("Hospital "+getLocalName()+": Han hecho todo lo posible, lo sentimos."); throw new FailureException("Han hecho todo lo posible"); } } } } FIPA-Query Este protocolo permite a un agente solicitar a otro un objeto o una comprobacin que devuelva un valor de verdad, y en funcin de que tipo de peticin sea ser un Query-if (comprobacin de verdad) o un Query-ref (cuando se pregunta por algn objeto). Los mensajes seran los siguientes: Query-If o Query-Ref, la solicitud. Agree si se acepta o refuse si se rechaza. Si se acept: Failure si ocurri algn error en el proceso, Inform-T/F con la respuesta si la consulta era un Query-If o Inform-Result si la consulta fue un Query-Ref. A continuacin se presenta un ejemplo que hace uso de estas clases. En este ejemplo un agente (representado por la clase Viajante) solicita al aeropuerto (representado por la clase Aeropuerto) que compruebe si tiene una reserva registrada.

Para que funcione bien, hay que lanzar primero el agente Aeropuerto y ha de llamarse Lavacolla. Para que la peticin del viajante se acepte, el nombre del mismo debe ser mayor que dos caracteres. Viajante package examples.practica5; import jade.core.AID; import jade.core.Agent; import jade.domain.FIPANames; import jade.lang.acl.ACLMessage; import jade.proto.AchieveREInitiator; public class Viajante extends Agent { protected void setup() { //Creamos el mensaje de la consulta. ACLMessage mensaje = new ACLMessage(ACLMessage.QUERY_IF); mensaje.setProtocol(FIPANames.InteractionProtocol.FIPA_QUERY); mensaje.setContent("Tengo la reserva?"); AID id = new AID(); id.setLocalName("Lavacolla"); mensaje.addReceiver(id); //Aadimos el comportamiento de la consulta. this.addBehaviour(new ComprobarInitiator(this, mensaje)); } class ComprobarInitiator extends AchieveREInitiator { public ComprobarInitiator(Agent agente, ACLMessage mensaje) { super(agente, mensaje); } protected void handleAgree(ACLMessage agree) { System.out.printf("Espere un momento por favor, estamos buscando en la Base de Datos.\n", agree.getSender().getLocalName()); } protected void handleRefuse(ACLMessage refuse) { System.out.printf("%s: En estos momentos todas las operadoras estan ocupadas. No podemos atenderle.\n", this.myAgent.getLocalName(), refuse.getSender().getLocalName()); } protected void handleNotUnderstood(ACLMessage notUnderstood) {

System.out.printf("%s: La operadora no entiende el mensaje.\n", this.myAgent.getLocalName(), notUnderstood.getSender().getLocalName()); } protected void handleInform(ACLMessage inform) { System.out.printf("La operadora informa: %s.\n", inform.getContent()); } protected void handleFailure(ACLMessage fallo) { System.out.println(this.myAgent.getLocalName() + ": Se ha producido un fallo."); } } } Aeropuerto package examples.practica5; import jade.core.Agent; import jade.domain.FIPANames; import jade.domain.FIPAAgentManagement.FailureException; import jade.domain.FIPAAgentManagement.NotUnderstoodException; import jade.domain.FIPAAgentManagement.RefuseException; import jade.lang.acl.ACLMessage; import jade.lang.acl.MessageTemplate; import jade.proto.AchieveREResponder; public class Aeropuerto extends Agent { protected void setup() { System.out.println(this.getLocalName() + ": Abriendo centralita..."); // Filtrado para recibir slo mensajes del protocolo FIPA-Query. MessageTemplate plantilla = AchieveREResponder.createMessageTemplate(FIPANames.InteractionProtocol.FIPA_ QUERY); this.addBehaviour(new ComprobarResponder(this, plantilla)); } class ComprobarResponder extends AchieveREResponder { public ComprobarResponder(Agent agente, MessageTemplate plantilla) { super(agente, plantilla); } protected ACLMessage handleRequest(ACLMessage request) throws NotUnderstoodException, RefuseException { System.out.printf("Operadora: Hemos recibido una llamada de %s solicitando informacion sobre su reserva.\n", request.getSender().getLocalName());

// Si el solicitante es vlido se acepta su peticin. if (comprobarSolicitante(request.getSender().getLocalName())) { System.out.println("Operadora: Espere un momento por favor..."); ACLMessage agree = request.createReply(); agree.setPerformative(ACLMessage.AGREE); return agree; } else { System.out.println(this.myAgent.getLocalName() + ": Todas las operadoras estan ocupadas."); throw new RefuseException("Por favor intentelo de nuevo mas tarde"); } } protected ACLMessage prepareResultNotification(ACLMessage request, ACLMessage response) throws FailureException { ACLMessage inform = request.createReply(); inform.setPerformative(ACLMessage.INFORM); String retorno = "No dispone de ninguna reserva"; if (comprobarSolicitante(request.getSender().getName())) retorno = "Si que ha hecho alguna reserva"; inform.setContent(retorno); return inform; } // Mtodo simple de aceptacin o rechazo de solicitudes. private boolean comprobarSolicitante(String nombre) { return (nombre.length() > 2); } } } Algunos otros de los protocolos de interes que estan implementados en la clase AchieveRE son: FIPA-Request-When que permite a un agente solicitar que otro lleve a cabo una accin dada cuando se cumple cierta precondicin. FIPA-Brokering cuya funcin es dar apoyo en interacciones de negociacin. 3.6.3 ContractNet Las clases ContractNet implementan el comportamiento del protocolo del mismo nombre, cuyo funcionamiento consiste en que el iniciador enva una propuesta a varios respondedores, evala las respuestas de stos, y selecciona la que ms le guste (puede no aceptar ninguna). Los mensajes que se intercambian son:

CFP (Call For Proposal), la solicitud de proposicin, especificando la accin a llevar a cabo y, si procede, las condiciones sobre la ejecucin. Los respondedores pueden enviar un Refuse para rechazar la solicitud, un NotUnderstood si hubo algn fallo en la comunicacin o un Propose con la propuesta que le hacen al iniciador. El iniciador evala todas las propuestas recibidas y enva Reject-Proposal para rechazarlas o Accept-Proposal para aceptarlas. Los respondedores cuya propuesta fue aceptada envan un Failure si algo sali mal, un Inform-Done si se realiz la accin con xito o un Inform-Result con los resultados de la accin si procede. El agente iniciador (ContractNetInitiator) posee dos mtodos importantes, el handlePropose que es llamado cada vez que se recibe una respuesta y el handleAllResponses que se llama cuando se recibieron todas las respuestas o el tiempo de espera se supera. Y el agente respondedor posee los mtopdos handleAcceptProposal y handleRejectProposal, que son llamados en funcin de si se acept su propuesta o no, y cuya principal caracterstica es que ambos reciben como parmetros todos los mensajes que se intercambiaron hasta el momento ambos agentes. A continuacin se presenta un ejemplo que hace uso de estas clases. En este ejemplo un agente cliente (representado por la clase Cliente) pedir precios para comprar un coche a varios agentes de venta de coches (representados por la clase Autos). Las ventas de coches podrn hacer una oferta o ninguna y el cliente se quedar con la mejor oferta que no supere el precio mximo establecido por l mismo (deber de pasarse como parmetro). Para que funcione bien hay que lanzar primero uno o mas autos para que se registren en el servicio de paginas amarillas, y a continuacin el agente Cliente. Cliente package examples.practica5; import jade.core.AID; import jade.core.Agent; import jade.domain.DFService; import jade.domain.FIPANames; import jade.domain.FIPAAgentManagement.DFAgentDescription; import jade.domain.FIPAAgentManagement.ServiceDescription; import jade.lang.acl.ACLMessage; import jade.proto.ContractNetInitiator; import java.util.Date; import java.util.Vector; public class Cliente extends Agent { //Nmero de ofertas que se considerarn. private int numeroDeOfertas; //Precio mximo que se pagar por un coche. private int precionMaximo;

protected void setup() { //El precio mximo se recibir como argumento de entrada. Object[] args = this.getArguments(); if (args != null && args.length == 1) { this.precionMaximo = Integer.parseInt(((String) args[0])); //Bsqueda del servicio de venta de coches en las pginas amarillas. ServiceDescription servicio = new ServiceDescription(); servicio.setType("Autos"); servicio.setName("Venta de coches"); DFAgentDescription descripcion = new DFAgentDescription(); descripcion.addLanguages("Espaol"); descripcion.addServices(servicio); try { DFAgentDescription[] resultados = DFService.search(this, descripcion); if (resultados.length <= 0) { System.out.println("No existen ventas de coches."); } else { System.out.println("Busco coche, hay " + resultados.length + " ofertas..."); //Creamos el mensaje CFP(Call For Proposal) cumplimentando sus parmetros ACLMessage mensajeCFP = new ACLMessage(ACLMessage.CFP); for (DFAgentDescription agente:resultados) { mensajeCFP.addReceiver(agente.getName()); } //Protocolo que vamos a utilizar mensajeCFP.setProtocol(FIPANames.InteractionProtocol.FIPA_CONTRA CT_NET); mensajeCFP.setContent("Busco coche, proponeis precios?"); //Indicamos el tiempo que esperaremos por las ofertas. mensajeCFP.setReplyByDate(new Date(System.currentTimeMillis() + 15000)); //Se aade el comportamiento que manejar las ofertas. this.addBehaviour(new ManejoOpciones(this, mensajeCFP)); } } catch (Exception e) { e.printStackTrace(); } } else { System.out.println("Debe de introducir el precio maximo que esta dispuesto a pagar (pasado como parametro)"); }

} // Fin del setup private class ManejoOpciones extends ContractNetInitiator { public ManejoOpciones(Agent agente, ACLMessage plantilla) { super(agente, plantilla); } //Manejador de proposiciones. protected void handlePropose(ACLMessage propuesta, Vector aceptadas) { System.out.printf("%s: Recibida oferta de autos %s. Ofrece un coche por %s euros.\n", this.myAgent.getLocalName(), propuesta.getSender().getLocalName(), propuesta.getContent()); } //Manejador de rechazos de proposiciones. protected void handleRefuse(ACLMessage rechazo) { System.out.printf("%s: Autos %s no tiene coches que ofrecer.\n", this.myAgent.getLocalName(), rechazo.getSender().getLocalName()); } //Manejador de respuestas de fallo. protected void handleFailure(ACLMessage fallo) { if (fallo.getSender().equals(myAgent.getAMS())) { //Esta notificacion viene del entorno de ejecucin JADE (no existe el receptor) System.out.println("AMS: Esta venta de autos no existe o no es accesible"); } else { System.out.printf("%s: Autos %s ha sufrido un fallo.\n", this.myAgent.getLocalName(), fallo.getSender().getLocalName()); } //Fall, por lo tanto, no recibiremos respuesta desde ese agente Cliente.this.numeroDeOfertas--; } //Mtodo colectivo llamado tras finalizar el tiempo de espera o recibir todas las propuestas. protected void handleAllResponses(Vector respuestas, Vector aceptados) { //Se comprueba si una venta de autos se pas del plazo de envo de ofertas. if (respuestas.size() < numeroDeOfertas) { System.out.printf("%s: %d ventas de autos llegan tarde.\n", this.myAgent.getLocalName(), Cliente.this.numeroDeOfertas respuestas.size()); } //Escogemos la mejor oferta int mejorOferta = Integer.MAX_VALUE;

AID mejorAutos = null; ACLMessage aceptado = null; for (Object resp:respuestas) { ACLMessage mensaje = (ACLMessage) resp; if (mensaje.getPerformative() == ACLMessage.PROPOSE) { ACLMessage respuesta = mensaje.createReply(); respuesta.setPerformative(ACLMessage.REJECT_PROPOSAL); aceptados.add(respuesta); //Si la oferta es la mejor (inferior a todas las otras) //Se almacena su precio y el AID de la venta de autos que la hizo. int oferta = Integer.parseInt(mensaje.getContent()); if (oferta <= precionMaximo && oferta <= mejorOferta) { mejorOferta = oferta; mejorAutos = mensaje.getSender(); aceptado = respuesta; } } } //Si hay una oferta aceptada se modifica su performativa. if (aceptado != null) { System.out.printf("%s: Decidido!!! Compro el coche de Autos %s\n", this.myAgent.getLocalName(), mejorAutos.getLocalName()); aceptado.setPerformative(ACLMessage.ACCEPT_PROPOSAL); } } //Manejador de los mensajes inform. protected void handleInform(ACLMessage inform) { System.out.printf("%s: Autos %s te ha enviado el contrato.\n", this.myAgent.getLocalName(), inform.getSender().getName()); } } } Autos package examples.practica5; import jade.core.Agent; import jade.domain.DFService; import jade.domain.FIPAException; import jade.domain.FIPANames; import jade.domain.FIPAAgentManagement.DFAgentDescription; import jade.domain.FIPAAgentManagement.FailureException; import jade.domain.FIPAAgentManagement.NotUnderstoodException; import jade.domain.FIPAAgentManagement.RefuseException; import jade.domain.FIPAAgentManagement.ServiceDescription; import jade.lang.acl.ACLMessage; import jade.lang.acl.MessageTemplate;

import jade.proto.ContractNetResponder; public class Autos extends Agent { protected void setup() { System.out.printf("Autos %s: A la espera de clientes...\n", this.getLocalName()); //Registro del servicio de venta de coches en las pginas amarillas. ServiceDescription servicio = new ServiceDescription(); servicio.setType("Autos"); servicio.setName("Venta de coches"); DFAgentDescription descripcion = new DFAgentDescription(); descripcion.setName(getAID()); descripcion.addLanguages("Espaol"); descripcion.addServices(servicio); try { DFService.register(this, descripcion); } catch (FIPAException e) { e.printStackTrace(); } //Se crea una plantilla que filtre los mensajes a recibir. MessageTemplate template = ContractNetResponder.createMessageTemplate(FIPANames.InteractionProtocol.FIPA_ CONTRACT_NET); //Aadimos los comportamientos ante mensajes recibidos this.addBehaviour(new CrearOferta(this, template)); } //Hacemos una simulacin para que pueda dar que existe o no coche (sobre un 80% probab). private boolean existeCoche() { return (Math.random() * 100 > 20); } //Calculamos un precio para el coche aleatoriamente (estar entre 8000 y 30000). private int obtenerPrecio() { return (int) (Math.random() * 22000) + 8000; } // Simula fallos en el clculo de precios. private boolean devolverPrecio() { return (int) (Math.random() * 10) > 1; } private class CrearOferta extends ContractNetResponder { public CrearOferta(Agent agente, MessageTemplate plantilla) {

super(agente, plantilla); } protected ACLMessage prepareResponse(ACLMessage cfp) throws NotUnderstoodException, RefuseException { System.out.printf("Autos %s: Peticion de oferta recibida de %s.\n", this.myAgent.getLocalName(), cfp.getSender().getLocalName()); //Comprobamos si existen ofertas disponibles if (Autos.this.existeCoche()) { //Proporcionamos la informacin necesaria int precio = Autos.this.obtenerPrecio(); System.out.printf("Autos %s: Preparando oferta (%d euros).\n", this.myAgent.getLocalName(), precio); //Se crea el mensaje ACLMessage oferta = cfp.createReply(); oferta.setPerformative(ACLMessage.PROPOSE); oferta.setContent(String.valueOf(precio)); return oferta; } else { //Si no hay ofertas disponibles rechazamos el propose System.out.printf("Autos %s: No tenemos ofertas disponibles.\n", this.myAgent.getLocalName()); throw new RefuseException("Fallo en la evaluacin."); } } protected ACLMessage prepareResultNotification(ACLMessage cfp, ACLMessage propose, ACLMessage accept) throws FailureException { //Hemos recibido una aceptacin de nuestra oferta, enviamos el albarn System.out.printf("Autos %s: Hay una posible oferta.\n", this.myAgent.getLocalName()); if (devolverPrecio()) { System.out.printf("Autos %s: Enviando contrato de compra.\n", this.myAgent.getLocalName()); ACLMessage inform = accept.createReply(); inform.setPerformative(ACLMessage.INFORM); return inform; } else { System.out.printf("Autos %s: Vaya!, ha fallado al enviar el contrato.\n", this.myAgent.getLocalName()); throw new FailureException("Error al enviar contrato."); } } protected void handleRejectProposal(ACLMessage cfp, ACLMessage propose, ACLMessage reject) {

//Nuestra oferta por el coche ha sido rechazada System.out.printf("Autos %s: Oferta rechazada por su excesivo precio.\n", this.myAgent.getLocalName()); } } } 3.6.4 Propose El protocolo FIPA-Propose implementa un comportamiento que consiste en que el iniciador le pide permiso al respondedor para realizar una accin, y si ste acepta la realiza y si no, no. Los mensajes intercambiados en la ejecucin de este protocolo son: Propose, con la propuesta de accin por parte del iniciador. Un Reject-Proposal o un Accept-Proposal en funcin de si acepta la propuesta o no. Una peculiaridad de las clases Propose es que la del respondedor (ProposeResponder) no dispone de mtodos handle, solamente dispone de un prepareResponse() que maneja la respuesta al Propose recibido, un registerPrepareResponse(), un createMessageTemplate() y algunos mtodos reset(). A continuacin se presenta un ejemplo que hace uso de estas clases. En este ejemplo el agente que Inicia (representado por la clase ProposeIni) le pedir permiso al que Responde (representados por la clase ProposeRes) para salir de clase. Slo si el Respondedor acepta, podr salir de clase. Para que funcione correctamente hay que crear el agente de nombre Puerta de tipo ProposeRes (que hay que lanzar primero) y un agente ProposeIni que llamaremos como queramos. ProposeIni package examples.practica5; import jade.core.AID; import jade.core.Agent; import jade.domain.FIPANames; import jade.lang.acl.ACLMessage; import jade.proto.ProposeInitiator; public class ProposeIni extends Agent { protected void setup() { //Se crea un mensaje PROPOSE. Se quiere pedir permiso para salir de clase. ACLMessage mensaje = new ACLMessage(ACLMessage.PROPOSE); mensaje.setProtocol(FIPANames.InteractionProtocol.FIPA_PROPOSE); mensaje.setContent("Puedo salir de clase?"); //Se aade el destinatario. AID id = new AID(); id.setLocalName("Puerta");

mensaje.addReceiver(id); //Aadir el comportamiento this.addBehaviour(new SalirClase(this, mensaje)); } private class SalirClase extends ProposeInitiator { public SalirClase(Agent agente, ACLMessage mensaje) { super(agente, mensaje); } //Manejar la respuesta en caso que acepte: ACCEPT_PROPOSAL protected void handleAcceptProposal(ACLMessage aceptacion) { System.out.printf("%s: Solicitud aceptada.\n", this.myAgent.getLocalName()); System.out.printf("%s: Saliendo de clase...\n", this.myAgent.getLocalName()); } //Manejar la respuesta en caso que rechace: REJECT_PROPOSAL protected void handleRejectProposal(ACLMessage rechazo) { System.out.printf("%s: Solicitud denegada.\n", this.myAgent.getLocalName()); System.out.printf("%s: No salgo de clase.\n", this.myAgent.getLocalName()); } } } ProposeRes package examples.practica5; import javax.swing.JOptionPane; import jade.core.Agent; import jade.domain.FIPANames; import jade.domain.FIPAAgentManagement.NotUnderstoodException; import jade.lang.acl.ACLMessage; import jade.lang.acl.MessageTemplate; import jade.proto.ProposeResponder; public class ProposeRes extends Agent { protected void setup() { System.out.printf("%s: Esperando propuestas...\n", this.getLocalName()); //Creamos la plantilla a emplear, para solo recibir mensajes con el protocolo FIPA_PROPOSE y la performativa PROPOSE MessageTemplate plantilla = ProposeResponder.createMessageTemplate(FIPANames.InteractionProtocol.FIPA_PR OPOSE);

//Aadimos el comportamiento "responderSalirClase()" this.addBehaviour(new ResponderSalirClase(this, plantilla)); } //Mtodo que permite al usuario decidir si acepta la propuesta o si la rechaza. private boolean checkContent(String agente, String propuesta) { if (JOptionPane.showConfirmDialog(null, propuesta, agente + " dice:", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { return true; } else { return false; } } private class ResponderSalirClase extends ProposeResponder { public ResponderSalirClase(Agent agente, MessageTemplate plantilla) { super(agente, plantilla); } //Preparacin de la respuesta. Recibe un mensaje PROPOSE y, segn su contenido, acepta o no. protected ACLMessage prepareResponse(ACLMessage propuesta) throws NotUnderstoodException { System.out.printf("%s: Proposicion recibida de %s.\n", this.myAgent.getLocalName(), propuesta.getSender().getLocalName()); System.out.printf("%s: La propuesta es: %s.\n", this.myAgent.getLocalName(), propuesta.getContent()); //Comprueba los datos de la propuesta if (ProposeRes.this.checkContent(propuesta.getSender().getLocalName(), propuesta.getContent())) { //Aceptacin de la propuesta. System.out.printf("%s: Dando permiso para salir de clase.\n", this.myAgent.getLocalName()); //Se crea la respuesta al mensaje con la performativa ACCEPT_PROPOSAL, pues se acepta. ACLMessage agree = propuesta.createReply(); agree.setPerformative(ACLMessage.ACCEPT_PROPOSAL); return agree; } else { //Rechazo de la propuesta. System.out.printf("%s: Prohibiendo que se salga de clase.\n", this.myAgent.getLocalName());

//Se crea la respuesta al mensaje con la performativa REJECT_PROPOSAL, pues se rechaza. ACLMessage refuse = propuesta.createReply(); refuse.setPerformative(ACLMessage.REJECT_PROPOSAL); return refuse; } } } } 3.6.5 Subscription El protocolo FIPA-Subscription consiste en que el iniciador le solicita al respondedor permiso para suscribirse, el respondedor procesa esa solicitud y la acepta o la rehecha. Si la acepta enva un mensaje con las condiciones de suscripcin, y lo hace de forma continua hasta que sufre un fallo y enva un failure o hasta que el iniciador cancela el envo. Los mensajes que se intercambian son: Subscribe, solicitando la suscripcin. El respondedor enva un Refuse si no acepta la propuesta de suscripcin, un Agree si la acepta y un Not-Understood si hubo algn fallo. Si la acept, despus enva un Inform-Result con las condiciones que establezca para la suscripcin. Para detener el envo, o bien sufre un fallo el respondedor y enva un Failure o bien enva un Cancel el iniciador. Si el proceso se detuvo porque el iniciador envi un Cancel, el respondedor manda un Inform-Done si todo se realiz exitosamente, o un Failure si algo no funcion correctamente. A continuacin se presenta un ejemplo que hace uso de estas clases. En este ejemplo el agente que inicia (representado por la clase SubscriptionIni) se suscribir en el agente que Responde (representado por la clase SubscriptionRes) para que le enve catlogos peridicamente. Cuando haya recibido 5 nmeros cancelar su suscripcin. Para que funcione correctamente hay que crear el agente MediaMarket de tipo SubscriptionRes (que hay que lanzar primero) y un agente SubscriptionIni que llamaremos como queramos. SubscriptionIni package examples.practica5; import jade.core.AID; import jade.core.Agent; import jade.domain.FIPANames; import jade.lang.acl.ACLMessage; import jade.lang.acl.MessageTemplate; import jade.proto.SubscriptionInitiator; public class SubscriptionIni extends Agent {

protected void setup() { //Se crea un mensaje de tipo SUBSCRIBE y se asocia al protocolo FIPASubscribe. ACLMessage mensaje = new ACLMessage(ACLMessage.SUBSCRIBE); mensaje.setProtocol(FIPANames.InteractionProtocol.FIPA_SUBSCRIBE); mensaje.setContent("Enviame todos las semanas el catalogo."); //Se aade el destinatario del mensaje AID id = new AID(); id.setLocalName("MediaMarket"); mensaje.addReceiver(id); //Aadir el comportamiento this.addBehaviour(new SuscribirCatalogo(this, mensaje)); } private class SuscribirCatalogo extends SubscriptionInitiator { private int suscripciones = 0; public SuscribirCatalogo(Agent agente, ACLMessage mensaje) { super(agente, mensaje); } //Maneja la respuesta en caso que acepte: AGREE protected void handleAgree(ACLMessage inform) { System.out.println(SubscriptionIni.this.getLocalName() + ": Solicitud aceptada."); } // Maneja la respuesta en caso que rechace: REFUSE protected void handleRefuse(ACLMessage inform) { System.out.println(SubscriptionIni.this.getLocalName() + ": Solicitud rechazada."); } //Maneja la informacion enviada: INFORM protected void handleInform(ACLMessage inform) { System.out.printf("%s: Informe recibido: %s.\n", SubscriptionIni.this.getLocalName(), inform.getContent()); this.suscripciones++; if (this.suscripciones == 5) { //Enviamos la cancelacin de la suscripcion this.cancel(inform.getSender(), false); //Comprobamos que se ha cancelado correctamente

this.cancellationCompleted(inform.getSender()); } } //Maneja la respuesta en caso de fallo: FAILURE protected void handleFailure(ACLMessage failure) { //Se comprueba si el fallo viene del AMS o de otro agente. if (failure.getSender().equals(myAgent.getAMS())) { System.out.println(SubscriptionIni.this.getLocalName() + ": El destinatario no existe."); } else { System.out.printf("%s: El agente %s fall al intentar realizar la accin solicitada.\n", SubscriptionIni.this.getLocalName(), failure.getSender().getName()); } } public void cancellationCompleted(AID agente) { //Creamos una plantilla para solo recibir los mensajes del agente que va a cancelar la suscripcin MessageTemplate template = MessageTemplate.MatchSender(agente); ACLMessage msg = blockingReceive(template); //Comprobamos que tipo de mensaje lleg: INFORM o FAILURE if (msg.getPerformative() == ACLMessage.INFORM) System.out.printf("%s : Suscripcion cancelada con el agente %s.\n", SubscriptionIni.this.getLocalName(), agente.getLocalName()); else System.out.printf("%s: Se ha producido un fallo en la cancelacin con el agente %s.\n", SubscriptionIni.this.getLocalName(), agente.getLocalName()); } } } SubscriptionRes package examples.practica5; import jade.core.Agent; import jade.core.behaviours.TickerBehaviour; import jade.domain.FIPAAgentManagement.NotUnderstoodException; import jade.lang.acl.ACLMessage; import jade.lang.acl.MessageTemplate; import jade.proto.SubscriptionResponder; import jade.proto.SubscriptionResponder.Subscription; import jade.proto.SubscriptionResponder.SubscriptionManager; import java.util.HashSet; import java.util.Set;

public class SubscriptionRes extends Agent { //Se crea una tabla indexada donde guardaremos las suscripciones realizadas. private Set<Subscription> suscripciones = new HashSet<Subscription>(); protected void setup() { System.out.println(this.getLocalName() + ": Esperando suscripciones..."); //Se crea una plantilla para que slo se admitan mensajes del protocolo FIPASubscribe MessageTemplate template = SubscriptionResponder.createMessageTemplate(ACLMessage.SUBSCRIBE); //Se aade un comportamiento que cada 5 segundos enva un mensaje a todos los suscriptores. this.addBehaviour(new EnviarSemanal(this, (long) 5000)); //Se aade un comportamiento que maneja los mensajes recibidos para suscribirse. //Habr que crear primero el SubscriptionManager que registrar y eliminar las suscripciones. SubscriptionManager gestor = new SubscriptionManager() { public boolean register(Subscription suscripcion) { suscripciones.add(suscripcion); return true; } public boolean deregister(Subscription suscripcion) { suscripciones.remove(suscripcion); return true; } }; this.addBehaviour(new HacerSuscripcion(this, template, gestor)); } //Comprueba la propuesta. En este caso si el contenido del mensaje tiene una longitud mayor que 2, devuelve true private boolean compruebaMensaje(String propuesta) { return (propuesta.length() > 2); } private class EnviarSemanal extends TickerBehaviour { public EnviarSemanal(Agent agente, long tiempo) { super(agente, tiempo); } public void onTick() { //Se crea y rellena el mensaje con la informacin que desea enviar. ACLMessage mensaje = new ACLMessage(ACLMessage.INFORM); mensaje.setContent(String.valueOf(getTickCount()));

//Se enva un mensaje a cada suscriptor for (Subscription suscripcion:SubscriptionRes.this.suscripciones) { suscripcion.notify(mensaje); } } } private class HacerSuscripcion extends SubscriptionResponder { private Subscription suscripcion; public HacerSuscripcion(Agent agente, MessageTemplate plantilla, SubscriptionManager gestor) { super(agente, plantilla, gestor); } //Mtodo que maneja la suscripcion protected ACLMessage handleSubscription(ACLMessage propuesta) throws NotUnderstoodException { System.out.printf("%s: SUSCRIBE recibido de %s.\n", SubscriptionRes.this.getLocalName(), propuesta.getSender().getLocalName()); System.out.printf("%s: La propuesta es: %s.\n", SubscriptionRes.this.getLocalName(), propuesta.getContent()); //Comprueba los datos de la propuesta if (SubscriptionRes.this.compruebaMensaje(propuesta.getContent())) { //Crea la suscripcion this.suscripcion = this.createSubscription(propuesta); try { //El SubscriptionManager registra la suscripcion this.mySubscriptionManager.register(suscripcion); } catch (Exception e) { System.out.println(SubscriptionRes.this.getLocalName() + ": Error en el registro de la suscripcin."); } //Acepta la propuesta y la enva ACLMessage agree = propuesta.createReply(); agree.setPerformative(ACLMessage.AGREE); return agree; } else { //Rechaza la propuesta y la enva ACLMessage refuse = propuesta.createReply(); refuse.setPerformative(ACLMessage.REFUSE); return refuse; } }

//Maneja la cancelacin de la suscripcion protected ACLMessage handleCancel(ACLMessage cancelacion) { System.out.printf("%s: CANCEL recibido de %s.\n", SubscriptionRes.this.getLocalName(), cancelacion.getSender().getLocalName()); try { //El SubscriptionManager elimina del registro la suscripcion this.mySubscriptionManager.deregister(this.suscripcion); } catch (Exception e) { System.out.println(SubscriptionRes.this.getLocalName() + ": Error en el desregistro de la suscripcin."); } //Acepta la cancelacin y responde ACLMessage cancela = cancelacion.createReply(); cancela.setPerformative(ACLMessage.INFORM); return cancela; } } } 3.7 Ejercicios Normas de entrega: Enviar el cdigo del ejercicio a: grupolimia1011@gmail.com En el email incluir: Nombre y Apellidos DNI Grupo (Bubal, Arenteiro, etc...) Cdigo fuente Ejercicio El siguiente ejercicio consiste en completar el siguiente cdigo correspondiente a 3 agentes. El objetivo es que 1 emisor enve mensajes a un receptor que solo recibe mensajes en Gallego, y a un receptor que solo recibe mensajes en Espaol. Nota: Tenemos 3 agentes: Receptor1, Receptor2 y Emisor. Al lanzar los agentes, se debe respetar el orden y nombre de los agentes recin citados. Emisor.java package examples. ... import ... import ... import ...

public class ... extends Agent { class EmisorComportaminento extends SimpleBehaviour { boolean fin = false; public void action() { System.out.println(getLocalName() +": Preparandose para enviar un mensaje a receptor"); AID id = ... id.setLocalName(...); AID id2= ... id2.setLocalName(...); // Creacin del objeto ACLMessage ACLMessage mensaje = new ...(ACLMessage.REQUEST); ACLMessage mensaje3 = new ...(ACLMessage.REQUEST); //Rellenar los campos necesarios del mensaje mensaje.setSender(getAID()); mensaje. ...("Gallego"); mensaje. ...(id); mensaje.setContent("mensaxe"); mensaje3.setSender(getAID()); mensaje3. ...("Espanol"); mensaje3. ...(id2); mensaje3.setContent("mensaje3"); //Envia el mensaje a los destinatarios ... (mensaje); System.out.println(getLocalName() +": Enviando hola a receptor"); System.out.println(mensaje.toString()); ... (mensaje3); System.out.println(getLocalName() +": Enviando hola a receptor2"); System.out.println(mensaje3.toString()); //Espera la respuesta ... mensaje2 = blockingReceive(); if (mensaje2!= null) { System.out.println(getLocalName() + ": acaba de recibir el siguiente mensaje: "); System.out.println(... .toString()); fin = true; } }

public boolean ...() { ... fin; } } protected void setup() { addBehaviour(new ...()); } }

Receptor.java package examples. ...; import ... import ... import ... import ...; public class ... extends Agent { class Comportamiento extends SimpleBehaviour { boolean fin = false; MessageTemplate plantilla = null; public Comportamiento () { AID emisor = new AID(); emisor.setLocalName("emisor"); //Devuelve una plantilla de mensaje que coincida con algn mensaje con un slot :sender dado. MessageTemplate filtroEmisor = ... .MatchSender(emisor); //Devuelve una plantilla de mensaje que coincida con algn mensaje con una perfomativa dada. MessageTemplate filtroInform = ... .MatchPerformative(ACLMessage.REQUEST); //Devuelve una plantilla de mensaje que conicida con algn mensaje con una slot :language dado MessageTemplate filtroIdioma = ... . ...("Gallego");

//Operacin lgica entre dos objetos de esta clase. plantilla = MessageTemplate.or(filtroInform,filtroEmisor);

plantilla = MessageTemplate.and(plantilla,filtroIdioma); } public void ...() { ... mensaje = receive(plantilla); if (mensaje!= null) { System.out.println(getLocalName() + ": ha recibido el siguiente mensaje: "); System.out.println(... .toString()); fin = true; }else { System.out.println(getLocalName() + ":Esperando mensajes..."); block(); } } public boolean ...() { return fin; } } protected void ...() { addBehaviour(new ...()); } } Receptor2.java package examples. ...; import ... import ... import ... import ... public class ... extends Agent { class Comportamiento extends SimpleBehaviour { boolean fin = false; MessageTemplate plantilla = null; public Comportamiento () { AID emisor = new AID();

emisor.setLocalName("emisor"); //Devuelve una plantilla de mensaje que coincida con algn mensaje con un slot :sender dado. MessageTemplate filtroEmisor = ... .MatchSender(emisor); //Devuelve una plantilla de mensaje que coincida con algn mensaje con una perfomativa dada. MessageTemplate filtroInform = ... .MatchPerformative(ACLMessage.REQUEST); //Devuelve una plantilla de mensaje que conicida con algn mensaje con una slot :language dado MessageTemplate filtroIdioma = ... . ...("Espanol");

//Operacin lgica entre dos objetos de esta clase. plantilla = MessageTemplate.or(filtroInform,filtroEmisor); plantilla = MessageTemplate.and(plantilla,filtroIdioma); } public void ...() { ... mensaje = receive(plantilla); if (mensaje!= null) { System.out.println(getLocalName() + ": ha recibido el siguiente mensaje: "); System.out.println(... .toString()); fin = true; }else { System.out.println(getLocalName() + ":Esperando mensajes..."); block(); } } public boolean ...() { return fin; } } protected void ...() { addBehaviour(new ...()); } }

3.8 Ejercicio (Comunicacin II (segunda parte)) Normas de entrega: Enviar el cdigo del ejercicio a: grupoAvia1011@gmail.com Nombre y Apellidos DNI Grupo (Bubal, Arenteiro, etc...) Cdigo fuente

El ejercicio a desarrollar consiste en la combinacin de dos de los protocolos de comunicacion vistos anteriormente. Se deber completar el codigo de los tres agentes que se indican a continuacion para que lleven a cabo la siguiente actividad: El "agente 1" lanzara una peticion Query-if al "agente 2" para que este le devuelve un numero. Este numero variar en funcion del "agente3". Para ello, el "Agente 2", en su metodo setup() lanzara un peticion de tipo propose al "Agente 3", pudiendo este aceptarlo o rechazarlo. En funcion de la decision del "Agente 3" el "Agente 2" devolver al "Agente 1" un valor u otro. El orden de ejecucin de los agentes ser: Agente3 -> Agente 2 -> Agente 1 Nota: Al agente 2 se le deber pasar como parametro el nombre que hayamos dado al agente 3, y al agente 1 el nombre que hayamos dado al agente2 Nota 2: La comunicacion entre el Agente 2 y el Agente 3 solo se lleva a cabo una vez ( durante el setup del Agente2 ), de forma que aunque se lancen varios "Agente 1" el resultado ser siempre el mismo. Para que todo vaya bien hay que dar respuesta a la peticin que salta en el Agente 3 antes de lanzar el Agente 1. AGENTE1.java package protocolos; //Cambiar segun convenga import jade.core.Agent; import jade.core.AID; import jade.lang.acl.ACLMessage; import jade.proto.AchieveREInitiator;

import jade.domain.FIPANames; public class ? extends Agent { protected void setup() { Object[] args = getArguments(); if (args != null && args.length == 1) { System.out.println("Solicitando un nuevo numero al agente intermedio"); ACLMessage msg = new ACLMessage(ACLMessage.?); msg.addReceiver(new AID((String) args[0], AID.ISLOCALNAME)); msg.setProtocol(FIPANames.InteractionProtocol.?); msg.?; addBehaviour(new ?); } else System.out.println("Debe escribir el nombre del agente intermedio (pasado como parametro)."); } class ManejadorInitiator extends AchieveREInitiator { public ?(Agent a,ACLMessage msg) { super(a,msg); } protected void ?(ACLMessage agree) { System.out.println("El agente intermedio " + agree.getSender().getName() + " informa que esta obteniendo el numero"); } protected void ?(ACLMessage refuse) { System.out.println("El agente intermedio " + refuse.getSender().getName() + " responde que se acabaron los numeros"); } protected void ?(ACLMessage notUnderstood) { System.out.println("El agente intermedio " + notUnderstood.getSender().getName() + " no puede entender el mensaje enviado."); } protected void ?(ACLMessage inform)

{ System.out.println("El agente intermedio " + inform.getSender().getName() + " nos devuelve el numero: " + inform.getContent()); } protected void ?(ACLMessage fallo) { if (fallo.getSender().equals(myAgent.getAMS())) { System.out.println("El agente intermedio no existe"); } else { System.out.println("El agente intermedio " + fallo.getSender().getName() + ": " + fallo.getContent().substring(1, fallo.getContent().length()-1)); } } } } AGENTE2.java package protocolos; //Cambiar segun convenga import jade.core.AID; import jade.core.Agent; import jade.domain.FIPANames; import jade.lang.acl.ACLMessage; import jade.lang.acl.MessageTemplate; import jade.proto.AchieveREResponder; import jade.proto.ProposeInitiator; public class ? extends Agent { private ? aceptado = ?; protected void setup() { Object[] args = getArguments(); if (args != null && args.length == 1) { //Configurar y lanzar comportamiento de inicio de peticionb ACLMessage mensaje = new ACLMessage(ACLMessage.?); mensaje.setProtocol(FIPANames.InteractionProtocol.?); mensaje.?; mensaje.?; this.addBehaviour(?);

System.out.println(this.getLocalName() + ": Esperando peticion..."); //Configurar y lanzar comportamiento de escucha MessageTemplate plantilla = AchieveREResponder.createMessageTemplate(FIPANames.InteractionProtocol.?); this.addBehaviour(?); } else System.out.println("Debe escribir el nombre del tercer agente (pasado como parametro)."); } class ComprobarResponder extends AchieveREResponder { public ?(Agent agente, MessageTemplate plantilla) { super(agente, plantilla); } protected ACLMessage ?(ACLMessage request){ System.out.printf("Recibido peticion de %s solicitando numero.\n", request.getSender().getLocalName()); ACLMessage agree = request.createReply(); agree.setPerformative(ACLMessage.AGREE); return agree; } protected ACLMessage prepareResultNotification(ACLMessage request, ACLMessage response){ System.out.printf("Comprobando numeros disponibles\n"); ACLMessage inform = request.createReply(); inform.setPerformative(ACLMessage.INFORM); String retorno; if ( aceptado ) retorno = "1"; else retorno = "0"; inform.setContent(?); System.out.printf("Mandando respuesta al agente inicial\n"); return ?; } } class ? extends ProposeInitiator {

public ?(Agent agente, ACLMessage mensaje) { super(agente, mensaje); } //Manejar la respuesta en caso que acepte: ACCEPT_PROPOSAL protected void handleAcceptProposal(ACLMessage aceptacion) { aceptado = ?; } //Manejar la respuesta en caso que rechace: REJECT_PROPOSAL protected void handleRejectProposal(ACLMessage rechazo) { aceptado = ?; } } }

AGENTE3.java package protocolos; //Cambiar segun convenga import javax.swing.JOptionPane; import jade.core.Agent; import jade.domain.FIPANames; import jade.lang.acl.ACLMessage; import jade.lang.acl.MessageTemplate; import jade.proto.ProposeResponder; public class ? extends Agent { protected void setup() { System.out.printf("Esperando peticiones...\n"); ? plantilla = ProposeResponder.createMessageTemplate(FIPANames.InteractionProtocol.?); this.addBehaviour(?); } //Metodo que permite al usuario decidir si acepta la propuesta o si la rechaza. private boolean checkContent(String agente, String propuesta) { if (JOptionPane.showConfirmDialog(null, propuesta, agente + " dice:", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { return true; } else { return false; } }

private class ResponderPermiso extends ProposeResponder { public ? (Agent agente, MessageTemplate plantilla) { super(agente, plantilla); } protected ACLMessage ?(ACLMessage propuesta){ System.out.printf("Peticion de permiso recibida de %s.\n", propuesta.getSender().getLocalName()); //Comprueba los datos de la propuesta if (agente3.this.checkContent(propuesta.getSender().getLocalName(), "Conceder permiso")) { System.out.printf("Permiso concedido\n"); ACLMessage agree = propuesta.createReply(); agree.setPerformative(ACLMessage.?); return ?; } else { System.out.printf("Permiso denegado\n"); ACLMessage refuse = propuesta.createReply(); refuse.setPerformative(ACLMessage.?); return ?; } } } }

Potrebbero piacerti anche