Agentes con JADE - II

Continuando con la serie de minitutoriales, toca dotar a nuestros agentes de inteligencia. Lo haremos añadiéndoles comportamientos. Un comportamiento es un algoritmo sencillo que nuestro agente ejecutará para intentar cumplir un objetivo. Evidentemente no hay inteligencia real en estos comportamientos, pero al tener muchos agentes interactuando entre ellos al final aparece un comportamiento global que podría calificarse como tal.

Al igual que con los agentes, para crear un comportamiento hemos de heredar de una clase de JADE, aunque esta vez tenemos varias para elegir. Dependiendo del tipo de comportamiento que queramos crear hemos de extender una clase u otra, y si no nos convence ninguno, extendemos la clase superior de la jerarquía y determinamos nosotros mismos las condiciones de ejecución del comportamiento.

En general un comportamiento tiene un método que es obligatorio redefinir, el método action(). Es en dicho método donde debemos introducir toda la lógica del comportamiento. Además existen varios métodos más que podemos redefinir (dependiendo de qué clase comportamiento estemos extendiendo). Uno de los más importantes es el método done() que permite saber cuándo se ha completado un comportamiento.

Antes de hablar de métodos hay que entender cómo se ejecutan los comportamientos. Los agentes tienen una cola de comportamientos, en ella se añaden los comportamientos que se deben ejecutar. Los agentes van ejecutando uno a uno los comportamientos, y si no se dan por terminados se vuelven a añadir a la cola. Podéis encontrar un diagrama y más detalles en esta wiki.

Los comportamientos más habituales son:

  • OneShotBehaviour: Se ejecuta una única vez en toda la vida del agente.
  • CyclicBehaviour: Tan pronto termina su ejecución se vuelve a añadir a la cola de comportamientos por ejecutar. Muy adecuado para la recepción de mensajes.
  • TickerBehaviour: Entre ejecución y ejecución deben haber pasado X (se le pasa como parámetro) milisegundos, puede que hayan pasado más pero nunca menos.
  • ParallelBehaviour: No ejecuta ningún código, si no que se le añaden subcomportamientos que serán ejecutados todos en paralelo cuando le toque ejecutarse a este comportamiento.
Todos estos comportamientos extienden la clase Behaviour, que también podemos utilizar en caso de que no se adapte ningún comportamiento predefinido a nuestro problema.

El método action() es al que el agente va a llamar cada vez que le toca ejecutarse a un comportamiento. Una vez completada la llamada comprobará si el comportamiento ha terminado llamando a done(). Si devolviera falso lo vuelve a meter en la cola para que se vuelva a llamar a action(). Es decir, que al método action() se llamará múltiples veces hasta que done() devuelva verdadero.

Por ejemplo, el método done() de OneShotBehaviour siempre devuelve cierto, mientras que el de CyclicBehaviour siempre devuelve falso. Si quisiéramos implementar una lógica de terminación más particular extenderíamos Behaviour directamente, y tendríamos que escribir el método done(). Más detalles sobre los tipos de comportamiento en esta wiki.

Código de ejemplo de un comportamiento que se ejecuta un determinado número de veces:

import jade.core.behaviours.Behaviour;

public class MyBehaviour extends Behaviour {

   private int count = 0;
   private int numVeces;

   public MyBehaviour(Agent agt, int numVeces) {
      super(agt);
      this.numVeces = numVeces;
   }

   @Override
   public void action() {
      count++;

      // Código del comportamiento
   }

   @Override
   public boolean done() {
      return count >= numVeces;
   }

}

Los comportamientos hay que añadirlos a los agentes llamado a un método definido en la clase Agent, el método addBehaviour(Behaviour behav). De la misma manera, si quisiéramos eliminar un comportamiento que aún no ha terminado llamaríamos a removeBehaviour(Behaviour behav). Obviamente para llamar a este segundo método nos hace falta una referencia al comportamiento que queramos eliminar del agente.

Desde dentro de un comportamiento también podemos acceder al agente, en la clase Behaviour está definido un atributo myAgent de tipo Agent que hace referencia al agente que posee el comportamiento. De esta forma podemos acceder a los métodos (por ejemplo send(AID to, ACLMessage msg)) del agente y a sus atributos. El atributo myAgent es de tipo Agent por lo que no podremos acceder a los campos y métodos que hayamos definido nosotros, a no ser que hagamos un casting. Pero en este último caso obligaríamos a que el comportamiento siempre esté asociado a ese tipo de agentes. Es preferible pasar los atributos del agente que necesite el comportamiento como parámetros en el constructor de este último.

El próximo tutorial será sobre paso de mensajes en JADE.

Show Comments