I. Introduction▲
Dans la programmation orientée agent, les différentes tâches d'un agent doivent obéir à certaines règles et doivent être écrites sous une forme compréhensible par la plateforme utilisée. Nous allons voir dans ce qui suit comment définir ces tâches et les utiliser dans JADE.
II. Vue générale▲
Pour qu'un agent JADE exécute une tâche, nous avons tout d'abord besoin de définir ces tâches. Les tâches dans JADE (appelées des behaviours ou des comportements) sont des instances de la classe jade.core.behaviours. Pour qu'un agent exécute une tâche, on doit la lui attribuer par la méthode addBehaviour(Behaviour b) de la classe jade.core.Agent.
Chaque Behaviour doit implémenter au moins les deux méthodes :
- action() : qui désigne les opérations à exécuter par le Behaviour ;
- done() : qui exprime si le Behaviour a terminé son exécution ou pas.
Il existe deux autres méthodes dont l'implémentation n'est pas obligatoire, mais qui peuvent être très utiles :
- onStart() : appelée juste avant l'exécution de ma méthode action() ;
- onEnd() : appelée juste après le retournement de true par la méthode done().
Des fois on a besoin de savoir quel est le propriétaire d'un Behaviour, et cela peut être connu par le membre myAgent du Behaviour en question.
JADE alloue un thread par agent, pour cela un agent exécute un Behaviour à la fois. L'agent peut exécuter plusieurs Behaviours simultanément en choisissant un bon mécanisme de passation d'un Behaviour à un autre (c'est à la charge du programmeur et non pas à la charge du JADE).
III. Les Behaviours du JADE▲
III-A. Les Behaviours simples▲
JADE offre trois types de Behaviours simples.
III-A-1. One-shot Behaviour▲
Un one-shot Behaviour est une instance de la classe jade.core.behaviours.OneShotBehaviour. Il a la particularité d'exécuter sa tâche une et une seule fois, puis il se termine. La classe OneShotBehaviour implémente la méthode done() et elle retourne toujours true.
III-A-2. Cyclic Behaviour▲
Un cyclic Behaviour est une instance de la classe jade.core.behaviours.CyclicBehaviour. Comme son nom l'indique, un cyclic Behaviour exécute sa tâche d'une manière répétitive. La classe CyclicBehaviour implémente la méthode done() qui retourne toujours false.
III-A-3. Generic Behaviour▲
Un Generic Behaviour est une instance de la classe jade.core.behaviours.Behaviour. Le Generic Behaviour vient entre le One-shot Behaviour et le Cyclic Behaviour du fait qu'il n'implémente pas la méthode done() et laisse son implémentation au programmeur, donc il peut planifier la terminaison de son Behaviour selon ses besoins.
III-A-4. Exemple▲
Voici un exemple sur l'utilisation des Behaviours simples
import
jade.core.Agent;
import
jade.core.behaviours.Behaviour;
import
jade.core.behaviours.CyclicBehaviour;
import
jade.core.behaviours.OneShotBehaviour;
public
class
SimpleAgent extends
Agent {
protected
void
setup
(
) {
// l'ajout d'un one-shot behaviour pour afficher un Hello world :D
addBehaviour
(
new
OneShotBehaviour
(
this
){
public
void
action
(
){
System.out.println
(
"Bonjour tout le monde je suis l'agent "
+
getLocalName
(
));
}
}
);
// l'ajout d'un CyclicBehaviour pour afficher un message à chaque fois qu'il s'exécute
addBehaviour
(
new
CyclicBehaviour
(
this
) {
public
void
action
(
) {
System.out.println
(
"cyclique... "
);
}
}
);
// l'ajout d'un generic behaviour
// le Behaviour s'arrête quand aléatoire reçoit la valeur 7
addBehaviour
(
new
RandomBehaviour
(
));
}
/**
* Inner class RandomBehaviour
*/
private
class
RandomBehaviour extends
Behaviour {
private
int
aleatoire ;
public
void
action
(
) {
aleatoire =
(
int
) (
Math.random
(
)*
10
);
System.out.println
(
"aleatoire ="
+
aleatoire);
}
public
boolean
done
(
) {
return
aleatoire ==
7
;
}
public
int
onEnd
(
) {
myAgent.doDelete
(
);
return
super
.onEnd
(
);
}
}
}
III-B. Les Behaviours planifiés▲
Pour planifier une tâche d'un agent JADE offre deux types de Behaviours.
III-B-1. WakerBehaviour▲
Le WakerBehaviour est implémenté de façon à exécuter la méthode onWake() après une période passée comme argument au constructeur. Cette période est exprimée en millisecondes. Le Behaviour prend fin juste après avoir exécuté la méthode onWake().
III-B-2. TickerBehaviour▲
Le TickerBehaviour est implémenté pour qu'il exécute sa tâche périodiquement par la méthode onTick(). La durée de la période est passée comme argument au constructeur.
III-B-3. Exemple▲
Voici un exemple d'un compte à rebours.
Le premier Behaviour affiche le temps restant chaque seconde.
Le deuxième arrête le compte à rebours et termine l'agent.
import
jade.core.Agent;
import
jade.core.behaviours.WakerBehaviour;
import
jade.core.behaviours.TickerBehaviour;
public
class
CompteaRebours extends
Agent {
protected
void
setup
(
) {
final
int
nombreDeSecondes =
(
int
)(
Math.random
(
)*
15
);
System.out.println
(
"compteur à rebours de "
+
nombreDeSecondes);
//ce Behaviour montre le temps restant
addBehaviour
(
new
TickerBehaviour
(
this
, 1000
) {
protected
void
onTick
(
) {
System.out.println
(
"Il reste "
+(
nombreDeSecondes-
getTickCount
(
))+
" seconds"
);
}
}
);
//ce Behaviour va arrêter le compte et terminer l'agent
addBehaviour
(
new
WakerBehaviour
(
this
, 1000
*
nombreDeSecondes) {
protected
void
handleElapsedTimeout
(
) {
System.out.println
(
"Terminé"
);
myAgent.doDelete
(
);
}
}
);
}
}
III-C. Les Behaviours composés▲
Vous allez rapidement vous rendre compte que les Behaviours présentés jusqu'ici ne peuvent pas répondre d'une manière efficace à tous les besoins d'un développeur d'un système multiagent. Pour cela JADE offre aussi un ensemble de Behaviours composés qui servent à présenter des tâches complexes. La classe mère de toutes les autres complexes est la classe jade.core.behaviours.CompositeBehaviour.
Une instance de cette classe, un Behaviour bien entendu, contient des sous-Behaviours, la méthode action() est déjà implémentée et invoque à chaque fois la méthode action() de l'un de ses sous-Behaviours. L'ordre d'exécution des Behaviours est à la charge des deux méthodes scheduleFirst() et scheduleNext() que les classes héritant de la classe CompositeBehaviour doivent implémenter. Le programmeur n'est pas dans l'obligation d'utiliser directement la classe CompositeBehaviour, car il dispose de trois classes filles.
III-C-1. SequentielBehaviour▲
La logique suivie dans les SequentielBehaviour est simple et intuitive. Le Behaviour commence par exécuter le premier sous-Behaviour et lorsque celui-là termine son exécution (sa méthode done() retourne true), il passe au prochain Behaviour, et ainsi de suite.
Les sous-Behaviours sont ajoutés au sequentielBehaviour par la méthode addSubBehaviour(). L'ordre de l'ajout détermine l'ordre d'exécution.
Voici un exemple :
import
jade.core.Agent;
import
jade.core.behaviours.OneShotBehaviour;
import
jade.core.behaviours.SequentialBehaviour;
import
jade.core.behaviours.WakerBehaviour;
public
class
Seq extends
Agent {
protected
void
setup
(
){
SequentialBehaviour comportementSequentiel =
new
SequentialBehaviour
(
);
comportementSequentiel.addSubBehaviour
(
new
OneShotBehaviour
(
){
@Override
public
void
action
(
) {
System.out.println
(
"le premier sous-comportement"
);
}
}
);
comportementSequentiel.addSubBehaviour
(
new
OneShotBehaviour
(
){
@Override
public
void
action
(
) {
System.out.println
(
"le second sous-comportement"
);
}
}
);
comportementSequentiel.addSubBehaviour
(
new
OneShotBehaviour
(
){
@Override
public
void
action
(
) {
System.out.println
(
"le dernier sous-comportement"
);
myAgent.doDelete
(
);
}
}
);
addBehaviour
(
comportementSequentiel);
}
}
III-C-2. FSMBehaviour▲
FSMBehaviour est une sorte de Behaviour qui implémente un automate à états finis dont chaque état correspond à l'exécution d'un sous-Behaviour.
L'introduction de l'automate se fait de la manière suivante :
- l'ajout d'un nouvel état se fait par la méthode registerState (Behaviour state, String name) ;
- l'ajout de l'état initial (il n'existe qu'un seul état initial) se fait par la méthode registerFirstState (Behaviour state, String name) ;
- l'ajout d'un état final (il est possible d'en avoir plusieurs) se fait par la méthode registerLastState (Behaviour state, String name).
- l'ajout d'une nouvelle transition se fait par la méthode registerTransition(String s1, String s2, int event) ;
- l'ajout d'une transition par défaut (la seule transition entre deux états ou bien la transition à prendre si aucune autre n'est prise) se fait par la méthode registerDefaultTransition(String s1, String s2, String[] toBeReset) :
- State : le Behaviour qui représente l'état,
- name :le nom de l'état ;
- s1 : l'état source,
- s2 : l'état destination,
- event: l'étiquette de la transition,
- String[] toBeReset : l'ensemble d'états pour lesquels on doit faire un reset() avant de les réexécuter parce qu'on ne peut pas réexécuter un Behaviour une autre fois avant de lui faire un reset().
Exemple : considérons l'automate suivant :
voici le FSM Behaviour qui le représente :
import
jade.core.Agent;
import
jade.core.behaviours.OneShotBehaviour;
import
jade.core.behaviours.FSMBehaviour;
public
class
Agent_FSM extends
Agent{
protected
void
setup
(
){
FSMBehaviour fsm =
new
FSMBehaviour
(
this
) {
public
int
onEnd
(
) {
System.out.println
(
"FSM behaviour terminé"
);
myAgent.doDelete
(
);
return
super
.onEnd
(
);
}
}
;
//définiton des états
fsm.registerFirstState (
new
UnComportement
(
),"A"
);
fsm.registerState
(
new
UnComportement
(
),"B"
);
fsm.registerState
(
new
UnComportement
(
),"C"
);
fsm.registerLastState
(
new
UnAutreComportement
(
),"D"
);
//définition des transactions
fsm.registerDefaultTransition
(
"A"
,"B"
);
fsm.registerTransition
(
"B"
,"B"
,1
);
fsm.registerTransition
(
"B"
,"C"
,0
);
fsm.registerTransition
(
"C"
,"C"
,1
);
fsm.registerTransition
(
"C"
,"D"
,0
);
addBehaviour
(
fsm);
}
//Inner Class
private
class
unComportement extends
OneShotBehaviour{
int
aleatoire;
@Override
public
void
action
(
) {
System.out.println
(
"exécution de l'état "
+
getBehaviourName
(
));
aleatoire =
(
int
)Math.random
(
) *
1
;
}
public
int
onEnd
(
){
return
aleatoire;
}
}
private
class
unAutreComprtement extends
OneShotBehaviour{
@Override
public
void
action
(
) {
System.out.println
(
"arrivée à l'état final"
);
}
}
}
III-C-3. ParallelBehaviour▲
Le parallelBehaviour permet d'exécuter plusieurs Behaviours en parallèle. Par parallèle, on comprend qu'après avoir invoqué la méthode action() d'un sous-Behaviour, on pointe sur le suivant sans attendre que le premier termine son exécution. L'ajout de sous-Behaviours se fait par la méthode addSubBehaviour() . Si on veut que le parallelBehaviour termine dès qu'un de ses sous-Behaviours termine, alors on doit passer à son constructeur l'argument WHEN_ANY. (Pour attendre la fin de tous les sous-Behaviours, on doit lui passer l'argument WHEN_ALL).
import
jade.core.Agent;
import
jade.core.behaviours.OneShotBehaviour;
import
jade.core.behaviours.ParallelBehaviour;
import
jade.core.behaviours.TickerBehaviour;
import
jade.core.behaviours.WakerBehaviour;
public
class
agent_parallel extends
Agent{
protected
void
setup
(
){
ParallelBehaviour comportementparallele =
new
ParallelBehaviour
(
ParallelBehaviour.WHEN_ANY);
comportementparallele.addSubBehaviour
(
new
WakerBehaviour
(
this
,1000
){
@Override
protected
void
handleElapsedTimeout
(
) {
System.out.println
(
"le temps est écoulé. "
);
myAgent.doDelete
(
);
}
}
);
comportementparallele.addSubBehaviour
(
new
TickerBehaviour
(
this
,50
){
int
aleatoire;
@Override
protected
void
onTick
(
) {
aleatoire=(
int
) (
Math.random
(
)*
100
);
System.out.println
(
"aleatoire = "
+
aleatoire);
if
(
aleatoire==
5
)
{
System.out.println
(
"Bingo!"
);
myAgent.doDelete
(
);
}
}
}
);
addBehaviour
(
comportementparallele);
}
}
III-D. Combiner plusieurs Behaviours composés▲
Il est possible de combiner les différents comportements composés pour créer des comportements plus complexes.
Par exemple, on peut combiner le FSMBehaviours et le parallelBehaviour précédents de la manière suivante :
attribuer à l'état C le parallelBehaviour. Si le Behaviour réussit à générer le 5 dans une seconde alors on passe à l'état D. Sinon on passe à l'état E
IV. Conclusion▲
IV-A. Bibliographie▲
- Developing multiagent systems with JADE edition wiley.
- JADE PROGRAMMER'S GUIDE de la documentation officielle.
IV-B. Remerciements▲
Je remercie dourouc05 pour la relecture et la correction orthographique.