<< | NetLogoIndex? | >>


1.  Avertissement

L'objectif de ce chapitre est de fournir un complément plus didactique que ce qui est présenté en cours. L'approche est par l'exemple cela se lit en testant et en mettant en oeuvre. D'autre part certains concepts peuvent être utilisés alors qu'ils n'ont pas encore été expliqués et développés en cours, mais ils sont généralement nécessaires pour obtenir une application complète. Tout ceci va s'appuyer sur un exemple qui va être développé au fil de l'eau.

2.  Le problème

Nous allons essayer de réaliser un petit programme simple permettant de simuler le comportement de deux populations de tortue : les craintives et les agressives. Elles possèdent toutes un cône de vision et elles fuiront ou se rapprocheront en fonction de ce qu'elles perçoivent.

3.  Au boulot

La solution va être construite en deux temps :

  1. Une seule population avec uniquement des tortues craintives ;
  2. Deux populations.

3.1  Une première version avec une unique population

Commençons par créer un squelette d'interface pour notre petit programme. Si vous regardez les modèles prédéfinis de NetLogo vous constaterez qu'ils ont presque toujours 2 boutons : setup et go. Le premier sert à initialiser la simulation et le second à lancer la simulation.

Il faut donc créer le premier bouton setup. Vous pouvez le faire par l'intermédiaire de l'interface en cliquant sur add et en sélectionnant Button si nécessaire.

Dans la partie commands vous allez donner le nom de la procédure associée au bouton. Cela fixe également l'intitulé par défaut du bouton. Le bouton apparaît en rouge car la procédure associée n'est pas définie.

Complétez votre interface en ajoutant un bouton go de la même façon.

Nous allons maintenant définir notre procédure setup qui crée les tortues. Pour cela il faut utiliser l'onglet code. Les tortues que nous allons représenter sont les craintives.

Une procédure NetLogo permet de définir ses propres commandes. Elle est composée de commandes prédéfinies comme forward, create-tutles ... que nous verrons au fur et à mesure, mais aussi d'appel à des procédures que vous avez définies et également d'instructions. Le squelette de base est le suivant :

 to setup
  ; On complète avec les commandes et les instructions  
 end

Le ; est sans effet, il permet de commenter le code. Étoffons notre code maintenant :

 to setup
   clear-all             ; On fait le ménage
   create-turtles 100    ; On crée 100 tortues
 end

Vous pouvez tester en cliquant en revenant dans l'onglet interface et en cliquant sur setup. Vous avez alors 100 tortues en tas au milieu de votre world. Nous avons vu 2 commandes :

  • clear-all souvent abrégé en ca qui réinitialise tout ;
  • create-turtles (ct) qui crée des tortues.

Pendant que vous êtes sous l'onglet interface je vous propose de rajouter un slider qui va nous permettre de fixer la population de tortues craintives.

Plutôt que fixer le nombres de tortue dans le code cela sera déterminé par la valeur du slider. On va également mieux répartir nos tortues dans le world.

 to setup
   clear-all                      ; On fait le ménage
   create-turtles Trouillardes    ; Valeur obtenue par le slider correspondant
   ask turtles                    ; On s'adresse à toutes nos tortues
   [
     set xcor random max-pxcor    ; On fixe aléatoirement l'abscisse entre 0 et max-pxcor
     set ycor random max-pycor    ; On fixe aléatoirement l'ordonnée entre 0 et max-pycor
     set heading random 360       ; On fixe aléatoirement l'orientation de la tortue
     set size 2                   ; On fixe la taille
     set color green              ; On fixe la couleur
   ]    
 end
  • create-turtles Trouillardes On créé le nombre de tortues fixé par le slider correspondant. Trouillardes est une variable globale connue dans l'ensemble du programme.
  • ask turtles .... on s'adresse à l'ensemble des tortues et on leur demande d’exécuter la liste de commande figurant entre [ et ].
 ask turtles 
 [
 ; liste de commande
 ]
Elle permet de s'adresser par exemple à une seule tortue en précisant son numéro (who).
 ask turtle 2
 [
  set color blue
 ]
Vous pouvez essayer.
Vous pouvez également l'utiliser pour les patches
 ask patches      ; Tous les patches
 [
  set pcolor white
 ]
Encore une fois n'hésitez pas à essayer.
  • set permet de donner une valeur à une variable. Chaque tortue a des variables propres (différentes pour chaque tortue) :
    • xcor et ycor ses coordonnées ;
    • heading orientation de la tortue. Lors de son prochain déplacement elle se déplace dans cette direction.
    • size la taille de la tortue.
    • color la couleur de la tortue.
    • hidden? la tortue est-elle visible ?
    • who le numéro de la tortue. Chaque tortue en possède un ce qui permet de la désigner.
  • random n retourne une valeur entière dans l'intervalle [0..n[
  • max-pxcor et max-pycor fixe les coordonnées maximales du world.

Si vous regardez le résultat vous pouvez constater que cela n'est pas satisfaisant. Je vous propose de modifier le world. Pour cela il faut cliquer sur le bouton Settings.

Location of originCorner
max-pxcor150
max-pycor150
world wrap horizontallyyes
world wrap horizontallyyes
Patch size3
on ticksyes

Nous allons rendre maintenant nos tortues mobiles et pour cela on va définir la procédure go. Elles vont se déplacer dans un premier temps de façon complément aléatoire.

 to go
   ask turtles
   [
     set heading heading + (random 30 - random 30)
     forward 1
   ]
 end
  • set heading heading + (random 30 - random 30) changement de direction aléatoire dans un cône de 30°
  • forward 1 (fd 1) avance d'une unité.

Vous pouvez maintenant tester avec le bouton go. Il peut être utile d'éditer ce bouton et cocher la case forever.

Je vous propose d'ajouter un switch Trace? qui va permettre de suivre la trajectoire de vos tortues.

 to go
   ask turtles
   [
     if Traces?             ; Si le switch est on
     [
       pen-down             ; on baisse le crayon
     ]
     set heading heading + (random 30 - random 30)
     forward 1
   ]
 end

Si vous exécutez ce programme, pensez à ralentir la vitesse avec le slider slower.

Une nouvelle fois on s'adresse à toutes les tortues grâce à la commande ask [..] et on a ajouté une instruction conditionnelle if.

 if condition
 [
  ; liste des commandes effectuées quand condition est vraie
 ]

condition représente une expression booléenne (TRUE ou FALSE) ou le résultat d'une fonction qui renvoie un booléen (reporter@@ booléen).

Il est possible d'utiliser également un si alors sinon.

 ifelse condition
 [
  ; liste des commandes effectuées quand condition est vraie
 ]
 [
  ; liste des commandes effectuées quand condition est fausse
 ]

Nos tortues doivent se comporter maintenant de façon plus sophistiquée et ne plus se déplacer au hasard. Nous allons considérer qu'une tortue panique s'il y a au moins une autre tortue dans sa zone de confort. Nous allons commencer par écrire une fonction qui teste cela et renvoie true si c'est le cas.

Il nous faut donc définir une fonction qui va retourner une valeur booléenne. NetLogo appelle désigne cela sous le nom de reporter. Le squelette de base est le suivant :

 to-report  nomDeVotreFonction
 ; Traitement
 report  resultat
 end 

La zone de confort va être définie par un angle et un rayon que l'on doit pouvoir fixer au niveau de l'interface. Le Rayon par un Input des éléments d'interface et l'Angle par un Slider.

Notre fonction panique? va s'écrire :

 to-report panique?
   report count other turtles in-cone Rayon Angle > 0 
 end
  • report retourne le résultat, c'est un booléen ici.
  • count Retourne le nombre d'agents de l'ensemble (agentset) donnée.
  • other retourne un ensemble d'agents qui est le même que celui reçu en entrée mais ne contenant plus l'agent appelant.
  • in-cone permet de doter une tortue d'un « cône de vision » vers l'avant. Le cône est défini par les deux entrées le rayon et l'angle de vision, cette dernière valeur représentant l'ouverture du cône. L'angle de vision peut prendre des valeurs de 0 à 360 et est centré sur le direction courante de la tortue. Le résultat est un ensemble d'agents ne contenant que les agents se trouvant dans le cône et appartenant au même ensemble d'agents que l'agent appelant. L'agent appelant peut aussi en faire partie. La distance à un patch est mesurée à partir du centre de patch.
 to setup
   clear-all                      ; On fait le ménage
   create-turtles Trouillardes    ; Valeur obtenue par le slider correspondant
   ask turtles                    ; On s'adresse à toutes nos tortues
   [
     set xcor random max-pxcor    ; On fixe aléatoirement l'abscisse entre 0 et max-pxcor
     set ycor random max-pycor    ; On fixe aléatoirement l'ordonnée entre 0 et max-pycor
     set heading random 360       ; On fixe aléatoirement l'orientation de la tortue
     set size 2                   ; On fixe la taille
     set color green              ; On fixe la couleur
   ]   
 end

 to go
   ask turtles
   [
     if Traces? [ pen-down ]      ; La tortue doit-elle laisser une  trace
     ifelse panique?              ; La tortue panique t-elle ?
     [
       set color red              ; Oui elle bascule en rouge
     ]
     [
       set color green
     ]
     set heading heading + (random Angle - random Angle) ; La tortue se déplace
     forward 1
   ]
 end

 to-report panique?
   report count other turtles in-cone Rayon Angle > 0 
 end

Une tortue qui panique fait demi-tour et devient rouge, sinon elle avance. On définit deux procédures :

  • avancer
  • ausecours
 to ausecours
   set color red
   set heading (heading - 180)
   forward 1
 end

 to avancer
   set color green
   set heading heading + (random Angle - random Angle) ; La tortue se déplace
   forward 1
 end

On va compter le nombre maximum de tortues paniquées à un temps t. Pour cela on va déclarer une variable globale et l'initialiser à 0.

 globals [ MaxPanique ]

 to setup
   ; ......
   set MaxPanique 0
 end

On crée ensuite au niveau de l'interface un monitor que l'on associe à notre variable globale.

 to go
   let m 0
   ask turtles
   [
     if Traces? [ pen-down ]      ; La tortue doit-elle laisser une trace
     ifelse panique?              ; La tortue panique t-elle ?
     [
       ausecours
     ]
     [
       avancer
     ]
   ]
   set m count turtles with [color = red]
   if m > MaxPanique [ set MaxPanique m]
 end

La procédure go est modifiée en conséquence. On déclare une variable locale m que l'on initialise à 0. Elle sert à stocker le nombre de tortue paniquée au temps t et s'il est plus grand on modifie en conséquence MaxPanique.

  • with retourne un nouvel ensemble d'agents ne contenant que les agents de l'ensemble ayant satisfait à la condition donnée.

Pour terminer cette partie on trace la courbe d'évolution des tortues paniquées. Pour cela il faut modifier l'interface et le code (en vert).

 globals [ MaxPanique ]

 to setup
   clear-all                      ; On fait le ménage
   create-turtles Trouillardes    ; Valeur obtenue par le slider correspondant
   ask turtles                    ; On s'adresse à toutes nos tortues
   [
     set xcor random max-pxcor    ; On fixe aléatoirement l'abscisse entre 0 et max-pxcor
     set ycor random max-pycor    ; On fixe aléatoirement l'ordonnée entre 0 et max-pycor
     set heading random 360       ; On fixe aléatoirement l'orientation de la tortue
     set size 2                   ; On fixe la taille
     set color green              ; On fixe la couleur
   ]   
   set MaxPanique 0
   reset-ticks
 end

 to go
   let m 0
   ask turtles
   [
     if Traces? [ pen-down ]      ; La tortue doit-elle laisser une trace
     ifelse panique?              ; La tortue panique t-elle ?
     [
       ausecours
     ]
     [
       avancer
     ]
   ]
   set m count turtles with [color = red]
   if m > MaxPanique [ set MaxPanique m]
   tick
 end

 to-report panique?
   report count other turtles in-cone Rayon Angle > 0 
 end

 to ausecours
   set color red
   set heading (heading - 180)
   forward 1
 end

 to avancer
   set color green
   set heading heading + (random Angle - random Angle) ; La tortue se déplace
   forward 1
 end

3.2  Une tortue qui n'a peur de rien

Ajoutons maintenant une tortue qui n'a peur de rien et qui avance droit devant quand il y en a une autre dans son champ de vision. Pour cela on va définir une variable propre à chaque tortue qui permet de savoir si elle est impressionnable? ou pas. Pour créer cette variable on utilise :

 turtles-own 
 [
   nonimpressionnable?
 ]

vous pouvez faire de même avec les patches (patches-own [...]). On va maintenant choisir une tortue de façon aléatoire qui n'a peur de rien.

 to setup
   clear-all                      ; On fait le ménage
   create-turtles Trouillardes    ; Valeur obtenue par le slider correspondant
   ask turtles                    ; On s'adresse à toutes nos tortues
   [
     set xcor random max-pxcor    ; On fixe aléatoirement l'abscisse entre 0 et max-pxcor
     set ycor random max-pycor    ; On fixe aléatoirement l'ordonnée entre 0 et max-pycor
     set heading random 360       ; On fixe aléatoirement l'orientation de la tortue
     set size 2                   ; On fixe la taille
     set color green              ; On fixe la couleur
     set impressionnable? false
   ]
   ask one-of turtles [ set impressionnable? true ]    
   set MaxPanique 0
   reset-ticks
 end 
  • one-of retourne un agent pris au hasard dans l'ensemble d'agents.

Il reste à définir son comportement. Pour cela on va modifier notre procédure ausecours à laquelle on va transmettre l'information si la tortue est impressionnable? ou pas. L'appel se fait donc sous la forme ausecours impressionnable? :

 to go
   let m 0
   ask turtles
   [
     if Traces? [ pen-down ]      ; La tortue doit-elle laisser une trace
     ifelse panique?              ; La tortue panique t-elle ?
     [
       ausecours nonimpressionnable?
     ]
     [
       avancer
     ]
   ]
   set m count turtles with [color = red]
   if m > MaxPanique [ set MaxPanique m ]
   tick
 end

Il faut modifier en conséquence la procédure ausecours qui reçoit maintenant un argument. Les arguments formels sont mis entre crochets.

 to ausecours [ courageuse? ]
   set color red
   if not courageuse?
     [ set heading (heading - 180) ]
   forward 1
 end

3.3  Une nouvelle espèce de tortue

Nous allons maintenant ajouter d'autres tortues avec un comportement différent. Ces dernières sont affectueuses et ont tendance à se diriger vers les tortues craintives. Pour cela nous modifions notre code précédent en créant deux espèces de tortues : les affectueuses et les craintives. La création d'une espèce se fait grâce à :

  • breed [<espece> <individu>] breed est la commande qui permet la création d'une espèce. On précise comment on désigne une espece et un individu@@ appartenant à cette espèce.

Cela nous donne donc :

 breed [craintives craintive]
 breed [affectueuses affectueuse]

Les craintives et les affectueuses sont toujours bien sûr des turtles. Néanmoins on utilise souvent cela pour s'adresser qu'à une partie des tortues.

  • ask craintives [ ... ]

Avant de définir le comportement de nos nouvelles tortues, on s'intéresse à adapter notre code afin de prendre en compte l'espèce craintives.

 globals [ MaxPanique ]

 breed [craintives craintive]
 breed [affectueuses affectueuse]

 craintives-own 
 [
   nonimpressionnable?
 ]

 to setup
   clear-all                      ; On fait le ménage
   create-craintives Trouillardes ; Valeur obtenue par le slider correspondant
   ask craintives                 ; On s'adresse aux craintives
   [
     set xcor random max-pxcor    ; On fixe aléatoirement l'abscisse entre 0 et max-pxcor
     set ycor random max-pycor    ; On fixe aléatoirement l'ordonnée entre 0 et max-pycor
     set heading random 360       ; On fixe aléatoirement l'orientation de la tortue
     set size 2                   ; On fixe la taille
     set color green              ; On fixe la couleur
     set impressionnable? false
   ]
   ask one-of craintives [ set nonimpressionnable? true ]    
   set MaxPanique 0
   reset-ticks
 end

 to go
   let m 0
   ask craintives
   [
     if Traces? [ pen-down ]      ; La tortue doit-elle laisser une trace
     ifelse panique?              ; La tortue panique t-elle ?
     [
       ausecours nonimpressionnable?
     ]
     [
       avancer
     ]
   ]
   set m count craintives with [color = red]
   if m > MaxPanique [ set MaxPanique m ]
   tick
 end

 to-report panique?
   report count other turtles in-cone Rayon Angle > 0 
 end

 to ausecours [ courageuse? ]
   set color red
   if not courageuse?
     [ set heading (heading - 180) ]
   forward 1
 end

 to avancer
   set color green
   set heading heading + (random Angle - random Angle) ; La tortue se déplace
   forward 1
 end

On crée les tortues correspondant à une espèce par :

  • create-<especes> <nombre>

Nous ajoutons ensuite nos tortues affectueuses qui sont au nombre de Calines défini par un slider.

Cela nous conduit à modifier la procédure setup dans laquelle on crée et initialise les craintives et les affectueuses. On regroupe des traitements identiques (position, couleur ...) dans une même procédure initCaracteristique. Dans l'extrait de code ci-dessous on pourra remarquer que dans un même temps on créée les affectueuses et on les initialise.

 to setup
   clear-all                      ; On fait le ménage
   create-craintives Trouillardes ; Valeur obtenue par le slider correspondant
   ask craintives                 ; On s'adresse à toutes les craintives 
   [
     initCaracteristique green
     set nonimpressionnable? false
   ]
   ask one-of craintives [ set nonimpressionnable? true ] 
   create-affectueuses Calines    ; Valeur obtenue par le slider correspondant
   [
     initCaracteristique blue
   ]
   set MaxPanique 0
   reset-ticks
 end

  to initCaracteristique [c] 
   set xcor random max-pxcor    ; On fixe aléatoirement l'abscisse entre 0 et max-pxcor
   set ycor random max-pycor    ; On fixe aléatoirement l'ordonnée entre 0 et max-pycor
   set heading random 360       ; On fixe aléatoirement l'orientation de la tortue
   set size 2                   ; On fixe la taille
   set color c                  ; On fixe la couleur
 end

La mobilité de nos tortues affectueuses va être aléatoire si elles ne perçoivent pas de tortues craintives dans leur voisinage sinon elles vont tenter de se rapprocher de la plus voisine.

 to caliner
   let copine craintives in-cone (Rayon + 1) Angle
   ifelse any? copine
   [
     face min-one-of copine [distance myself]
   ]
   [  
     set heading heading + (random Angle - random Angle) ; La tortue se déplace
   ]
     forward 1  
 end

On réutilise le cône de vision et copine contient l'ensemble des craintives visibles en fonction de ce cône. On teste si la liste copine est vide avec any?.

  • any? teste si la liste d'agents est vide (TRUE/FALSE).

Si la liste n'est pas vide la tortue s'oriente vers la plus proche et avance.

  • face <uneTortue> modifie la direction de la tortue de façon à ce qu'elle pointe vers uneTortue.
  • min-one-of <ensembleDAgents> [<reporter>] retourne l'agent de l'ensemble d'agent agentset qui a la plus petite valeur pour le reporter donné (fonction retournant une valeur). S'il y a égalité, cette commande retourne un agent pris au hasard parmi ceux ayant cette plus petite valeur.
  • distance <agent> Retourne la distance qu'il y a entre l'agent appelant et la tortue ou le patch spécifié par agent.
  • myself signifie « la tortue ou le patch qui m'a demandé de faire ce que je suis justement en train de faire » (self correspond à « moi »).
 globals [ MaxPanique ]

 breed [craintives craintive]
 breed [affectueuses affectueuse]

 craintives-own 
 [
   nonimpressionnable?
 ]

 to setup
   clear-all                      ; On fait le ménage
   create-craintives Trouillardes ; Valeur obtenue par le slider correspondant
   ask craintives                 ; On s'adresse à toutes les craintives 
   [
     initCaracteristique green
     set nonimpressionnable? false
   ]
   ask one-of craintives [ set nonimpressionnable? true ] 
   create-affectueuses Calines    ; Valeur obtenue par le slider correspondant
   [
     initCaracteristique blue
   ]
   set MaxPanique 0
   reset-ticks
 end


 to go
   let m 0
   ask craintives
   [
     if Traces? [ pen-down ]      ; La tortue doit-elle laisser une trace
     ifelse panique?              ; La tortue panique t-elle ?
     [
       ausecours nonimpressionnable?
     ]
     [
       avancer
     ]
   ]
   ask affectueuses 
   [ 
     if Traces? [ pen-down ]      ; La tortue doit-elle laisser une trace  
     caliner 
   ]
   set m count craintives with [color = red]
   if m > MaxPanique [ set MaxPanique m ]
   tick
 end

 to-report panique?
   report count other turtles in-cone Rayon Angle > 0 
 end

 to ausecours [ courageuse? ]
   set color red
   if not courageuse?
     [ set heading (heading - 180) ]
   forward 1
 end

 to avancer
   set color green
   set heading heading + (random Angle - random Angle) ; La tortue se déplace
   forward 1
 end


 to caliner
   let copine craintives in-cone (Rayon + 1) Angle
   ifelse any? copine
   [
     face min-one-of copine [distance myself]
   ]
   [  
     set heading heading + (random Angle - random Angle) ; La tortue se déplace
   ]
     forward 1  
 end

 to initCaracteristique [c] 
   set xcor random max-pxcor    ; On fixe aléatoirement l'abscisse entre 0 et max-pxcor
   set ycor random max-pycor    ; On fixe aléatoirement l'ordonnée entre 0 et max-pycor
   set heading random 360       ; On fixe aléatoirement l'orientation de la tortue
   set size 2                   ; On fixe la taille
   set color c                  ; On fixe la couleur
 end

4.  Adaptation du problème : proies prédateurs

Vous pouvez maintenant étendre le problème au problème de proies/prédateurs.