Sie sind auf Seite 1von 34

Comportamientos de los Agentes

2.1 Qué es un comportamiento


2.2 Añadir y eliminar comportamientos
2.3 Métodos de un comportamiento
2.4 Ejecución de los comportamientos
2.5 Flujo de control de un agente
2.6 Tipos de comportamiento
2.6.1 Comportamiento genérico
2.6.2 Comportamientos simples
2.6.3 Comportamientos compuestos
2.6.4 Comportamientos temporales
2.7 Ejercicios

2.1 Qué es un comportamiento

Un comportamiento o behaviour hace referencia a una funcionalidad que incorpora el agente.

Los comportamientos especifican tareas o servicios que realiza un agente para lograr sus
objetivos. Cada comportamiento puede realizar una tarea simple como "Envia este mensaje" o
"compra X " aunque también se pueden crear comportamientos compuestos.

Cada tarea del agente sará una instancia de una clase que deber heredar de la clase Behaviour.

class MiComportamiento extends Behaviour{



}

Por este motivo, e código JAVA que implementa esa funcionalidad ha de importar el paquete:

jade.core.behaviours.*

Aunque bastaría con importar simplemente la clase Behaviour que se encuentra en:
jade.core.behaviours.Behaviour

Nota: En el siguiente enlace se encuentra una descripción de todos los métodos disponibles en
la Clase Behaviour

Los agentes están programados en base a sus comportamientos. La programación basada en


comportamientos debe realizar los siguientes pasos:

1. Determinar qué debe ser capaz de hacer el agente.


2. Asociar cada funcionalidad con un comportamiento.
3. Escoger el tipo de comportamientos
4. Dejar a JADE la tarea del scheduling (un solo comportamiento se está ejecutando en cada
instante).

2.2 Añadir y eliminar comportamientos

La clase Agent provee dos métodos para añadir y borrar comportamientos a un


agente: addBehaviour(Behaviour) y removeBehaviour(Behaviour). Estos métodos permiten
gestionar la entrada y salida de los objetos Behaviour en la cola del planificador. El planificador va
ejecutando según una política round-robin los objetos behaviour que se encuentran en una cola
FIFO.

Los comportamientos pueden ser añadidos o eliminados en cualquier momento de la vida del
agente, desde el método setup() o desde cualquier otro comportamiento, incluso desde otros
agentes.

Crear un comportamiento no es más que crear una clase privada dentro de la clase del agente y
asociarlo a ese agente mediante el método addBehaviour(Behaviour). Añadir un comportamiento
debe ser visto como la ejecución de un nuevo thread dentro del agente.

En el siguiente ejemplo se puede ver como se añade un comportamiento desde el


método setup() del agente.

import jade.core.Agent;
import jade.core.behaviours.*;

public class MiAgente extends Agent{

protected void setup(){


//Aqui es donde se añade el comportamiento.
addBehaviour(new MiComportamiento1());
}
//Este es el comportamiento.
private class MiComportamiento1 extends Behaviour{
public void action(){
System.out.println("Mi nombre es: "+getName() );
System.out.println("Soy el comportamiento del agente");

}
public boolean done(){
return true;
}
}
}

En el siguiente ejemplo se muestra como se puede añadir un comportamiento desde otro


comportamiento.

Para ello usaremos una variable de la clase Behaviour llamada myAgent que funciona como una
referencia al agente que esta ejecutando el comportamiento, es decir, al agente al que pertenece el
comportamiento.

import jade.core.Agent;
import jade.core.behaviours.*;

public class MiAgente extends Agent{

protected void setup(){


//Aqui es donde se añade el comportamiento.
addBehaviour(new MiComportamiento1());
}
//Este es el comportamiento.
private class MiComportamiento1 extends Behaviour{
public void action(){
System.out.println("Mi nombre es: "+getName() );
System.out.println("Soy el primer comportamiento");

myAgent.addBehaviour(new MiComportamiento2());
}
public boolean done(){
return true;
}
}
//Este es el otro comportamiento
private class MiComportamiento2 extends Behaviour{
public void action(){
System.out.println("Soy el segundo comportamiento");
}
public boolean done(){
return true;
}
}
}

Además de añadir nuevos comportamientos, también se pueden eliminar comportamientos de un


agente con el método removeBehaviour(Behaviour).
Así, si en el ejemplo anterior quisiéramos borrar el primer comportamiento desde el segundo
comportamiento bastaría con hacer una llamada a removeBehaviour() dentro del método action
del segundo comportamiento:

package examples.practica2;

import jade.core.Agent;
import jade.core.behaviours.*;

public class Ejemplo1 extends Agent{

private Behaviour comp;

// Inicialización del agente


protected void setup()
{
//Creamos un comportamiento: un objeto de la clase
MiComportamiento1
comp = new MiComportamiento1();
//Aqui es donde se añade el comportamiento.
addBehaviour(comp);
}

//Definición de un comportamiento
private class MiComportamiento1 extends Behaviour{

// define la acción a ser ejecutada cuando se ejecute el


comportamiento.
public void action(){
System.out.println("Mi nombre es: "+getName() );
System.out.println("Soy el primer comportamiento");
// Añade un comportamiento desde otro comportamiento.
myAgent.addBehaviour(new MiComportamiento2());
}

// Determina si el comportamiento ha sido completado o no.


// Si el comportamiento ha finalizado, éste se elimina de la cola
de comportamientos activos.
public boolean done(){
return true;
}
}

//Definición de un segundo comportamiento


private class MiComportamiento2 extends Behaviour{
public void action(){
System.out.println("Soy el segundo comportamiento");
myAgent.removeBehaviour(comp);//Borramos el primer
comportamiento;
}
public boolean done(){
return true;
}
}

2.3 Métodos de un comportamiento

Toda clase que herede de Behaviour deberá implementar:

- el método action().

 Este método define la acción a ser ejecutada cuando se ejecute el comportamiento. Debe incluir el
código de las acciones a realizar cuando se ejecute el comportamiento.
 Es invocado cuando se produce el evento asociado al comportamiento.
 Es recomendable que los métodos action() no tengan un tiempo de ejecución alto ya que mientras
que se ejecutan no pueden ser interrumpidos por otro comportamiento.
- el método done().

 Es invocado cuando finaliza la ejecución del método action().


 Este método determina si el comportamiento ha sido completado o no.Devuelve un booleano
(true si ha terminado o false en caso contrario).
 Si el comportamiento ha finalizado, éste se elimina de la cola de comportamientos activos.
 Se puede utilizar una marca que se activa cuando se quiere que finalice el comportamiento (se
evalúa su valor en el método done()).

El siguiente ejemplo muestra como el funcionamiento de los método action() y done() de un


comportamiento.

package examples.practica2;

import jade.core.Agent;
import jade.core.behaviours.*;

public class Ejemplo2 extends Agent{

// Inicialización del agente


protected void setup(){
// Añade un comportamiento
addBehaviour(new MiComportamiento());
}

// Finalización del agente


protected void takeDown(){
System.out.println("La escala ha terminado");
}

// Definición de un comportamiento
private class MiComportamiento extends Behaviour{
private int estado = 0;

// Función que realiza MiComportamiento


public void action(){
switch(estado){
case 0: System.out.println("Do"); break;
case 1: System.out.println("Re"); break;
case 2: System.out.println("Mi"); break;
case 3: System.out.println("Fa"); break;
case 4: System.out.println("Sol");break;
case 5: System.out.println("La"); break;
case 6: System.out.println("Si"); break;
case 7:{
System.out.println("Do");
myAgent.doDelete();
break;
}
}
estado++;
}

// Comprueba si el comportamiento ha finalizado.


public boolean done(){
return (estado > 7);
}
}
}

Un comportamiento también puede ser bloqueado utilizando el método block(). Este método
permite bloquear un comportamiento hasta que algún acontecimiento ocurra (típicamente, hasta
que un mensaje llegue). Este no afecta a los demás comportamientos de un agente.
Cuando el método action() termina, el método block() coloca el comportamiento en la cola de
comportamientos bloqueados.

Además, un objeto de la clase Behaviour puede bloquearse durante una cantidad limitada de
tiempo que se pasa por valor al método block(), expresado en milisegundos.

Debe tenerse en cuenta que el método block() no es como el método sleep() de los Threads. El
método block() no para la ejecución del comportamiento sino que espera a que finalice el
método action(). Una vez finalizado, si el comportamiento no termina, éste pasa a la lista de
comportamientos bloqueados durante el tiempo que indique el método block() o hasta que se
reciba un nuevo mensaje.

package examples.practica2;

import jade.core.Agent;
import jade.core.behaviours.*;

public class Ejemplo3 extends Agent{

// Inicialización del agente


protected void setup()
{
addBehaviour( new MiComportamiento() );
}

// Finalización del agente


protected void takeDown()
{
System.out.println("****Agente finalizado****");
}

// Definición de un comportamiento
private class MiComportamiento extends Behaviour
{
int numeroEjecuciones = 1;

// // Función que realiza MiComportamiento


public void action()
{
System.out.println("Esta es la ejecucion
"+numeroEjecuciones);

//lo bloqueamos durante un segundo


block(1000);
System.out.println("Despues de 1000 milisengundos");
numeroEjecuciones++;
}

// Comprueba si el comportamiento ha finalizado


public boolean done(){
if(numeroEjecuciones>10)
{
myAgent.doDelete();
return true;
}
else return false;
}
}
}

Un comportamiento bloqueado puede reiniciar su ejecución (desbloquearse) cuando alguna de las


siguientes condiciones ocurre:
 El agente al que pertenece ese comportamiento recibe un mensaje ACL. En este caso el
comportamiento se saca de la cola de comportamientos bloqueados y se coloca al final de la cola
de comportamientos activos. Cuando se produce la llegada de un mensaje, todos los objetos de la
cola de bloqueados se planifican y deben comprobar si el mensaje es para ellos o no. en el caso
de que un objeto no sea el destinatario debe volver a bloquearse.
 Una interrupción asociada con este comportamiento por el método block() expira. Por ejemplo, si
un objeto se ha bloqueado durante dos segundos, al finalizar este tiempo, el objeto se
desbloqueará.
 El método restart() es llamado explícitamente por el comportamiento, así se fuerza el desbloqueo.

La clase Behaviour también proporciona dos métodos llamados onStart() y onEnd(). Estos
métodos pueden ser sobrescritos por el usuario para ejecutar acciones anteriores o posteriores a la
ejecución del método action(). Estos métodos se implementan solamente una vez.

- El método onStart() se ejecuta justo antes de la ejecución del método action().

- El método onEnd() se ejecuta antes de finalizar el comportamiento (después de que el


método done() devuelva true) y devuelve un entero que representa un valor de terminación para el
comportamiento. Este valor dependerá de las condiciones de ejecución implementadas en el
comportamiento.

Se debe recordar que onEnd() se llama después de que el comportamiento se haya completado y
haya sido eliminado de la cola de comportamientos del agente. Sin embargo, llamando al
método reset() dentro de onEnd() no es suficiente para que se repita cíclicamente la tarea
representada por ese comportamiento y además se debe añadir dicho comportamienro de nuevo al
agente como se muestra en el siguiente ejemplo:

package examples.practica2;

import jade.core.Agent;
import jade.core.behaviours.*;

public class Ejemplo4 extends Agent {

// Inicialización del agente


protected void setup(){
// Añadir un comportamiento.
addBehaviour(new MiComportamiento());
}

// Definición de un comportamiento
private class MiComportamiento extends Behaviour{
// Este método se ejecuta justo antes de la ejecución del método
action()
public void onStart()
{
System.out.println("Esto se hace cada vez que se inicia el
comportamiento");
}

// Funcion a realizar por el comportamiento


public void action(){

System.out.println("Hola a todos.");

//lo bloqueamos durante un segundo


block(1000);
System.out.println("Despues de 1 segundo");
}

// Comprueba si el comportamiento ha finalizado


public boolean done(){
return true;
}

// Se ejecuta antes de finalizar el comportamiento


public int onEnd(){
// Hace que el comportamiento se reinicie al finalizar.
reset();
myAgent.addBehaviour(this);

return 0;
}
}
}

2.4 Ejecución de los comportamientos

Cada agente tiene un planificador o scheduler de comportamientos. La política de planificación se


realiza de forma preemptiva para todos los comportamientos activos de la cola circular, es decir,
ejecutando un comportamiento hasta que libera el control, sin poder interrumpirla hasta que ésta
acabe (esto ocurre cuando finaliza el método action()).

En contra de lo que pudiera parecer, los comportamientos no son ejecutados concurrentemente.


Se puede pensar que los comportamientos son como los hilos de ejecución JAVA. Igual que las
threads en Java, en un agente pueden estar activos a la vez tantos comportamientos como sea
necesario. Sin embargo, a diferencia de las threads en JAVA, el decidir qué comportamiento se
ejecuta en cada momento es tarea del programador, mientras que en JAVA lo decide la máquina
virtual. Esto es así para que cada agente equivalga únicamente a un único thread, con el
consiguiente ahorro de ciclos de CPU y memoria que esto implica.

La mayor parte de estos comportamientos serán utilizados para el intercambio de mensajes:


- ya sea para recibirlos y actuar en consecuencia
- o ya sea para enviarlos.

El funcionamiento de los comportamientos está implementado a 2 niveles:

 Una cola circular de los comportamientos activos


 Una cola con los comportamientos bloqueados

Un comportamiento puede bloquearse (block()) cuando el método action() termina, entonces éste
se coloca en la cola de los comportamientos bloqueados.
Cuando este comportamiento se desbloquea (por una de las razones vistas anteriormente) se saca
de la cola de bloqueados y se coloca al final de la cola de comportamientos activos.

Es importante recordar que, cuando el método action() se está ejecutando, ningún otro
comportamiento (de ese mismo agente) puede continuar su ejecución hasta que termine dicho
método.
2.5 Flujo de control de un agente

En la figura que se muestra a continuación se representa el flujo de control de un agente básico:


Inicialización, realización de la tarea y limpieza y finalización; es decir, el camino que atraviesa un
agente desde que comienza su ejecución hasta que finaliza y se elimina. Como puede verse, lo
primero a ejecutar es el método setup(). Tras esto se comprueba que el agente sigue vivo y
después se selecciona el siguiente comportamiento a ejectuar del conjunto de comportamientos
que aun le quedan al agente. Se ejecuta su método b.action() y tras esto se pregunta si ha
finalizado. Es posible que no lo haya hecho ya que un comportamiento puede ser o un simple trozo
de código que se ejecuta una sola vez o bien varias veces dependiendo de otros factores. Si está
ejecutado se elimina del conjunto de comportamientos del agente y no vuelve a ejecutarse. En otro
caso, se vuelve a comenzar.
¿Cómo sería la ejecución de un agente que tenga el siguiente comportamiento?

a) No se ejecuta puesto falta por definir el método onStart().


b) El comportamiento se bloquea durante 1 segundo y el planificador pasa el control al siguiente
comportamiento de la cola.
c) No finaliza nunca puesto que el método action() no finaliza.
d) Finaliza siempre puesto que el método done() devuelve siempre true.

public class MiComportamiento extends Behaviour {

private boolean salir = true;


private int cont = 0;

public void action(){

while (salir) {
if (cont > 0) {
salir = true;
}
cont++;
}
block(1000);
}

public boolean done(){


return true;
}
}

2.6 Tipos de comportamientos

En muchas ocasiones los agentes realizan, o tratan de realizar, funcionalidades complejas que
pueden llegar a implicar tareas simultáneas forzando a implementar agentes multihilo, lo que
puede causar problemas. JADE proporciona un sistema de comportamientos (behaviours) que
ayudan al usuario a construir sistemas multiagente y reutilizar código.

El paquete jade.core.behaviours contiene las clases que se usan para implementar


comportamientos básicos de agentes. Los agentes JADE programan sus comportamientos con un
solo hilo y el decidir qué comportamiento se ejecuta en cada momento es tarea del desarrollador
del agente. De esta manera se eliminan los problemas de sincronización entre comportamientos
concurrentes que acceden al mismo recurso, haciendo que cada agente sea equivalente a un
único hilo, con el consiguiente ahorro de ciclos de CPU y memoria. Por tanto, pueden estar activos
varios comportamientos a la vez, pero sólo uno de ellos se ejecutará en un momento determinado.
2.6.1 Comportamiento Genérico

Se corresponde con la clase abstracta Behaviour. Mantienen un estado del agente y en base a él
se ejecutan diferentes operaciones. Finalizan cuando cierta condición se cumple.
Un ejemplo sencillo de este tipo de comportamiento es el código escrito en el apartado 2.3.

2.6.2 Comportamientos simples

Este tipo de comportamientos se corresponden con la clase SimpleBehaviour que representa a


comportamientos atómicos, que suelen realizar tareas simples.

Se utilizarán los siguientes metodos:

1. reset ():Devuelve el comportamiento a su estado inicial.


2.6.2.1 OneShotBehaviour

En este tipo de comportamiento el método done() siempre devuelve "true", de forma que sólo se
ejecuta una vez y de forma ininterrumpida.

package examples.practicaTres;
import jade.core.Agent;
import jade.core.behaviours.*;

public class OneShot extends Agent{

public void setup() {


MyOneShotBehaviour c = new MyOneShotBehaviour();
addBehaviour(c);
}

protected void takeDown(){


System.out.println("Ejecucion finalizada");
}

private class MyOneShotBehaviour extends OneShotBehaviour {


public void action() {
System.out.println("Ejecutamos la accion una sola vez");
myAgent.doDelete();
}
}
}//

2.6.2.2 CyclicBehaviour

Representa un comportamiento que debe ejecutarse una serie de veces.

 El método done() devuelve false.


 Se mantiene activo tanto tiempo como esté activo el agente.
 Hay riesgo de que se pueda quedar con toda la CPU.
package examples.practicaTres;
import jade.core.Agent;
import jade.core.behaviours.*;

public class Cyclic extends Agent{

public void setup() {


MyCyclicBehaviour c = new MyCyclicBehaviour();
addBehaviour(c);
}

protected void takeDown(){


System.out.println("Ejecucion finalizada");
}

private class MyCyclicBehaviour extends CyclicBehaviour {


public void action() {
System.out.println("Ejecutamos la accion ciclicamente");
}
}
}//

2.6.3 Comportamientos compuestos

Esta clase abstracta modela comportamientos a partir de la composición de otros comportamientos


(hijos). Está compuesta por diferentes subcomportamientos que se pueden ejecutar siguiendo
diferentes políticas de planificación. Las diferentes políticas vienen determinadas por la subclase
elegida, que puede ser del tipo:SequentialBehaviour, ParallelBehaviour y FSMBehavior. Se
utilizarán los siguientes metodos:

1. checkTermination(): Se ejecuta después de la ejecución de cada hijo para saber cuando se debe
terminar el comportamiento.
2. getCurrent(): Devuelve el comportamiento hijo que actualmente está programado para ejecutarse.
3. scheduleFirst(): Programa al primer hijo para ser ejecutado.
4. scheduleNext(): Programa al siguiente hijo para ser ejecutado.
2.6.3.1 FSMBehaviour

Esta clase permite definir una Máquina de Estados finita mediante subcomportamientos. Cada
subcomportamiento representa un estado de la máquina y las transiciones se van produciendo
según la salida de dichos estados.
Se utilizarán los siguientes metodos:

1. registerFirstState(behaviour b, String n ): Establece cúal es el estado inicial.


2. registerState(behaviour b, String n ): Registra los estados intermedios.
3. registerLastState(behaviour b, String n ): Registra el estado final.
4. registerTransition(String s1, String s2, int evento ): Registra las transiciones entre estados.
5. registerDeafultTransition(String s1, String s2) es otro de los métodos de la clase FSMBehaviour
que permite definir una transición por defectoentre dos estados. Este tipo de transiciones no están
marcadas con una etiqueta, y sólo se ejecutan en el caso de que el retorno del estado anterior no
coincida con ninguna otra transición.

De manera secuencial, y definiendo transiciones entre estados, se implementa la acción que debe
realizar el comportamiento.
Hay que tener en cuenta una serie de cuestiones como:

 FSMBehaviour carece de método action(), por lo que la implementación de estados y transiciones


debe realizarse en el constructor, en su método onStart() o justo después de añadir el
comportamiento en el nacimiento del agente.
 Hay que identificar los estados definiendo unas constantes cómo etiquetas.
 Hay que registrar los distintos comportamientos que componen FSMBehaviour a modo de estados,
registrando cada uno de ellos cómo primer estado, último estado o estado(s) intermedio(s).
 El agente finaliza cuando se termina de ejecutar algún sub-comportamiento que se haya registrado
como estado final.
 Las transiciones puede ser por defecto o teniendo en cuenta un valor de salida del comportamiento
origen, que será devuelto por el método onEnd() de cada comportamiento, valor que dependerá de
las condiciones de ejecución que se implementen en cada estado/comportamiento.
package examples.practicaTres;
import jade.core.Agent;
import jade.core.behaviours.*;
import java.lang.*;

public class FSM extends Agent {


private static final String ONE_STATE = "UNO";
private static final String TWO_STATE = "DOS";
private static final String THREE_STATE = "TRES";
private static final String ERROR_STATE= "CERO";
private final int UNO = 1;
private final int DOS = 2;
private final int TRES = 3;
private final int CERO = 0;
private String entrada="";

public void setup() {


entrada="231231231";
MiFSMBehaviour b = new MiFSMBehaviour(this,entrada);
addBehaviour(b);
}

private class MiFSMBehaviour extends FSMBehaviour{


private int transicion=0;
private String entrada="";

public MiFSMBehaviour(Agent _agente,String ent){


super(_agente);
entrada=ent;
}

public void onStart(){


registerFirstState(new OneBehaviour(),ONE_STATE);
registerState(new TwoBehaviour(), TWO_STATE);
registerState(new ThreeBehaviour(), THREE_STATE);
registerLastState(new ErrorBehaviour(),ERROR_STATE);
registerTransition(ONE_STATE, TWO_STATE, DOS);
registerTransition(TWO_STATE, THREE_STATE,TRES);
registerTransition(THREE_STATE,ONE_STATE,UNO);
registerDefaultTransition(ONE_STATE, ERROR_STATE);
registerDefaultTransition(TWO_STATE, ERROR_STATE);
registerDefaultTransition(THREE_STATE, ERROR_STATE);
}
protected boolean checkTermination(boolean currentDone,int
currentResult){
System.out.println(" ** Terminado estado numero:
"+currentName);
return super.checkTermination(currentDone,currentResult);
}

public int getEntrada(){


int tipoEvento = CERO;
if (entrada.length()<1) return tipoEvento;
else tipoEvento=Integer.parseInt(entrada.substring(0,1));
entrada=entrada.substring(1,entrada.length());
return tipoEvento;
}

private class OneBehaviour extends OneShotBehaviour {


public void action(){System.out.println("() Primer
estado");}
public int onEnd() { return getEntrada();}
}

private class TwoBehaviour extends OneShotBehaviour {


public void action(){System.out.println("() Estado del
segundo comportamiento"); }
public int onEnd() { return getEntrada();}
}

private class ThreeBehaviour extends OneShotBehaviour {


public void action(){System.out.println("() Estado del
tercer comportamiento"); }
public int onEnd() { return getEntrada();}
}

private class ErrorBehaviour extends OneShotBehaviour {


public void action(){System.out.println("() Error de
estado");}
}

} //class MiFSMBehaviour
}//class MiAgente
2.6.3.2 SequentialBehaviour

Esta subclase de CompositeBehaviour ejecuta los subcomportamientos de manera secuencial y


termina cuando todos ellos han terminado (termina la ejecución de action()). Se utiliza cuando una
tarea compleja se puede descomponer en una secuencia de pasos atómicos.

Para añadir los subcomportamientos se utiliza el método addSubBehaviour() y se ejecutarán en el


orden en que sean agregados.

package examples.practicaTres;
import jade.core.Agent;
import jade.core.behaviours.*;

public class MiAgente2632 extends Agent{

public void setup() {


SequentialBehaviour s = new SequentialBehaviour(this);
s.addSubBehaviour(new Contador(this, "A", 3));
s.addSubBehaviour(new Contador(this, "B", 2));
s.addSubBehaviour(new Contador(this, "C", 4));
s.addSubBehaviour(new Contador(this, "D", 3));
s.addSubBehaviour(new Contador(this, "E", 5));
addBehaviour(s);
}

protected void takeDown(){


System.out.println("ejecucion finalizada");
}

private class Contador extends SimpleBehaviour {


int c;
int lim;
String nombre;

public Contador(Agent a, String nombre, int lim) {


super(a);
this.nombre = nombre;
this.c = 0;
this.lim = lim;
}

public void action () {


c++;
System.out.println("contador " + nombre + ": " + c);
}

public boolean done () {


return c == lim;
}
}
}

2.6.3.3 ParallelBehaviour

Esta subclase de CompositeBehaviour ejecuta los subcomportamientos de manera concurrente y


termina cuando se cumple una determinada condición sobre la terminación de los
subcomportamientos. Define las constantes que han de ser notificadas al constructor para que el
comportamiento termine cuando:

 todos los subcomportamientos lo han hecho (ParalellBehaviour.WHEN_ALL) (por defecto)


 un subcomportamiento cualquiera termine (ParalellBehaviour.WHEN_ANY)
 cuando un número especificado de subcomportamientos terminen (indicar un entero)

Para añadir los subcomportamientos se utiliza el método addSubBehaviour() como en el


comportamiento secuencial.
package examples.practicaTres;
import jade.core.Agent;
import jade.core.behaviours.*;

public class MiAgente2633 extends Agent{

public void setup() {


ParallelBehaviour s = new ParallelBehaviour(this,
ParallelBehaviour.WHEN_ALL);
//ParallelBehaviour s = new ParallelBehaviour(this,
ParallelBehaviour.WHEN_ANY);
//ParallelBehaviour s = new ParallelBehaviour(this, 3);
s.addSubBehaviour(new Contador(this, "A", 3));
s.addSubBehaviour(new Contador(this, "B", 2));
s.addSubBehaviour(new Contador(this, "C", 4));
s.addSubBehaviour(new Contador(this, "D", 3));
s.addSubBehaviour(new Contador(this, "E", 5));
addBehaviour(s);
}
protected void takeDown(){
System.out.println("ejecucion finalizada");
}

private class Contador extends SimpleBehaviour {


int c;
int lim;
String nombre;

public Contador(Agent a, String nombre, int lim) {


super(a);
this.nombre = nombre;
this.c = 0;
this.lim = lim;
}

public void action () {


c++;
System.out.println("contador " + nombre + ": " + c);
}

public boolean done () {


return c == lim;
}
}
}

2.6.4 Comportamientos temporales

JADE proporciona además dos comportamientos adicionales sencillos para ejecutar operaciones
en determinados instantes de tiempo.

Cosas que es importante recordar:


1. El método block() no detiene la ejecución del comportamiento actual, sino que inicia un contador
que evitará que se vuelva a ejecutar el mismo comportamiento hasta haber superado un tiempo
establecido u ocurra un determinado acontecimiento (por ejemplo la llegada de un mensaje o una
llamada al método restart()).
2. Llamar más de una vez al método block() durante la ejecución del mismo comportamiento no tiene
efecto, JADE sólo soporta una invocación a este método por cada comportamiento, de tal manera
que sólo será relevante la última de estas sentencias.
3. El método sleep() es heredado de la clase Thread y cada agente se ejecuta en un único hilo por
tanto, su invocación detendrá no sólo la ejecución del comportamiento actual, sino también la
ejecución de todos los comportamientos del agente.
4. El método stop() detiene el comportamiento desde el que se llama a dicho método sin esperar.

2.6.4.1 Comportamiento TickerBehaviour

Permite definir un comportamiento cíclico que ejecutará periódicamente una tarea (el periodo se
indica en el constructor) que será implementada sobrecargando el método abstracto onTick(). Sus
métodos action() y done() ya están implementados. Además contamos con el
método getTickCount() que devuelve el número de ticks desde el último reseteo del
comportamiento.

package examples.practicaTres;
import jade.core.Agent;
import jade.core.behaviours.*;

public class MiAgente2641 extends Agent{

long tini;

protected void setup(){


tini = System.currentTimeMillis();
addBehaviour(new miTicker(this, 1000));
}

private class miTicker extends TickerBehaviour{

int minticks;

public miTicker(Agent a, long intervalo){


super(a, intervalo);
minticks = 0;
}
public void reset () {
super.reset();
//minticks = 0;
System.out.println("reseteo!");
}

protected void onTick() {


long tfin = System.currentTimeMillis() - tini;
int nticks = getTickCount(); // obtenemos el numero de ticks
desde el último reset
minticks++;
if (nticks == 5) {
System.out.println("[" + tfin + "ms.] tick = " + nticks +
", mitick = " + minticks + " y reseteo");
reset();
} else {
System.out.println("[" + tfin + "ms.] tick = " + nticks +
", mitick = " + minticks);
}
}
}
}

2.6.4.2 Comportamiento WakerBehaviour

Este comportamiento implementa un comportamiento one-shot que se ejecuta una vez haya
transcurrido un tiempo especificado. Los métodos action() y done() ya están implementados y la
funcionalidad del comportamiento debe ser implementada sobrecargando el método
abstracto onWake(), después del cual el comportamiento se dará por completado. En el siguiente
ejemplo veremos el funcionamiento de WakerBehaviour, al mismo tiempo que comprobaremos
como se comporta un agente cuando ejecutamos el método sleep() a diferencia de block().

package ...;
import jade.core.Agent;
import jade.core.behaviours.*;

public class ... extends Agent {


private long tini;

protected void setup() {


tini = System.currentTimeMillis();

addBehaviour(
new ...(..., 1000) {
protected void ...() {
System.out.println("[ 1 ] Tiempo transcurrido: "+
(System.currentTimeMillis()-tini) + "ms.");
}
}
);
/*
addBehaviour(
new ...(..., 10000){
protected void ...() {
System.out.println("[*2*] Tiempo transcurrido: " +
(System.currentTimeMillis()-tini) + "ms.");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("error");
}
}
}
);*/
}
}

Por último indicar que aunque TickerBehaviour y WakerBehaviour son conceptualmente subclases
de las clases Cyclic y OneShot, están implementadas como extensiones de Simplebehaviour y
Behaviour

2.7 Ejercicios

Ejemplo:

Veremos un ejemplo de un agente que muestra por pantalla los días de la semana y al acabar la
semana finaliza:

import jade.core.Agent;
import jade.core.behaviours.*;

public class ejemploComportamiento extends Agent{

private Behaviour comp;

// Inicializacion del agente


protected void setup(){
.
.
.
}

// Finalización del agente


protected void takeDown(){
System.out.println("La semana ya acabo");
}

// Definición de un comportamiento
private class MiComportamiento extends Behaviour{
private int dia = 0;

// Función que realiza MiComportamiento


public void action(){
.
.
.
}

// Comprueba si el comportamiento ha finalizado.


public boolean done(){
...
}
}
}

Ejercicio Grupo Sil:

En este ejercicio veremos un poco como es el flujo de control de un agente. Para ello debemos:
a) Crear dos comportamientos C1 y C2.
b) Hacer que ambos comportamientos ejecuten un println y se bloqueen durante un tiempo.
c) Poner que ambos comportamientos ejecuten el mismo número de veces el println.
d) Poner el tiempo de bloqueo de C1 mayor que el de C2 (el doble por ejemplo).
e) Hacer que cuando C2 acabe, finalice la ejecución del agente.

Con esto veremos que aunque C1 debería seguir imprimiendo por pantalla el mensaje, al
eliminarse el agente, el comportamiento no sigue.

Normas de envío:

Enviar el ejercicio a la dirección de correo:


Adjuntar los siguientes datos:

Nombre y Apellidos
Grupo

Código de ayuda:

package ...;

import ...;
import jade.core.Agent;

public class ... extends ...{

private Behaviour comp1,comp2;

protected void setup(){


System.out.println("Agente inicializado");
.
.
.
}

protected void takeDown(){


System.out.println("Agente Finalizado");
}

private class MiComportamiento1 extends ...{


int repeticiones = 0;

public void ...{


System.out.println("Comportamiento 1 Iniciado");
}
public void action(){
System.out.println("C1: Me voy a bloquear");
...
repeticiones++;
}

public boolean ...{


...
}

public int ... {


System.out.println("Comportamiento 1 Finalizado");
return 0;
}
}

private class MiComportamiento2 extends ...{

private int repeticiones=0;

public void ...{


System.out.println("Comportamiento 2 Iniciado");
}

public void ...{


System.out.println("C2: Me voy a bloquear");
...
repeticiones++;
}

public boolean done(){


...
}

public int ... {


System.out.println("Comportamiento 2 Finalizado");
...
return 0;
}
}
}
Ejercicio 2: GRUPO BUBAL

Instrucciones de entrega

Enviar un correo a grupobubal1011@gmail.com:

 nombre y apellidos, DNI y grupo (Limia, Sil, ...)


 Código fuente del ejercicio resuelto.

Instrucciones para compilar y ejecutar el ejemplo

 Crear NombreDeClase.java, para cada ejercicio y añadirlo a $JADE_HOME$\src\examples\practicaTres


 Para compilar, situarse en $JADE_HOME$\src y ejecutar: javac examples\practicaTres\*.java
 Ejecutar plataforma JADE: Situarse en $JADE_HOME$ y ejecutar: java jade.Boot -gui
 Ejecutar agente: Situarse en $JADE_HOME$\src y ejecutar: java jade.Boot -
container nombreAgente:examples.practicaTres.NombreDeClase

Ejercicio propuesto

En este ejercicio vamos a desarrollar los comportamientos paralelos y secuenciales. Para ello simularemos la
siguiente figura. Tendremos en cuenta que:

 A y B se ejecutarán 2 veces
 PA, PB se ejecutarán 1 vez
 PC, PD ,PE se ejecutarán 3 veces
 F, G se ejecutarán 1 vez
Examina el código del siguiente agente y complétalo :

package examples.practicaTres;

import ...;
import ...;

public class ... extends ...{

public void ...{

// crear comportamiento paralelo que finalice cuando se ejecuten


todos los subcomportamientos
... p = new ...;

p. ...;
p. ...;
p. ...;
p. ...;
p. ...;

// crear comportamiento secuencial


... s = new...;
s. ...;
s. ...;

s. ...;//llamar al comportamiento paralelo

s. ...;
s. ...;

//añadir comportamiento
...;

}
protected void ...{
System.out.println("ejecucion finalizada");
}

private class Contador extends ... {


int c;
int lim;
String nombre;

public Contador(Agent a, String nombre, int lim) {


super(a);
this.nombre = nombre;
this.c = 0;
this.lim = lim;
}

public void action () {


c++;
System.out.println("contador " + nombre + ": " + c);
}

public boolean done () {


...
}
}

Bibliografia:

http://programacionjade.wikispaces.com/Comportamientos

Das könnte Ihnen auch gefallen