Un monde de moutons et de loups...
D'après le cours de Frédéric Mandon sous licence Creative Commons BY NC SA, http://creativecommons.org/licenses/by-nc-sa/3.0/fr/.
Objectif
On veut modéliser le fonctionnement d’un écosystème, avec de l’herbe, des moutons et des loups : les moutons mangent l'herbe, les loups mangent les moutons.
Cette simulation est discrète : tous les « tours de jeu », les moutons ainsi que les loups se déplacent, mangent éventuellement, meurent parfois, et l’herbe pousse.
L’intérêt est d'observer l'évolution de la "population" de chaque protagoniste, l'herbe, les moutons et les loups.
1. Les moutons et l’herbe
Classe Monde
Principe
Cette classe est la carte sur laquelle évoluent les moutons.
Elle a pour attribut ( entre autres ) un tableau carré carte de dimension 50 x 50 (ou plus), qui représente une prairie.
Chaque case du tableau représente une zone sur laquelle pousse de l’herbe.
Ce tableau contient des coefficients entiers qui codent la présence ou pas d'herbe :
- Si la valeur de l’entier est inférieure à l’entier duree_repousse il n’y a pas d’herbe
- si la valeur est supérieure, il y en a, et l’herbe repousse à une vitesse donnée ( entier duree_repousse entre 1 et 100, on peut mettre 30)
Le coefficient dans une case du tableau est réinitialisé à 0 lorsqu’un mouton « occupe » la case et mange l’herbe.
A chaque "battement d’horloge" modélisant l'évolution du temps, on augmente la valeur dans chaque case de 1 pour modéliser la pousse de l'herbe ( vous verrez la gestion du temps dans la classe Simulation ).
Attributs
- dimension
- duree_repousse
- carte
Méthodes
herbePousse()herbeMangee(x,y), où x et y sont les coordonnées d'une case de la carte.nbHerbe()qui renvoie le nombre de carrés de la carte qui contiennent de l'herbe.getCoefCarte(x,y), où x et y sont les coordonnées d'une case de la carte. C’est une méthode qui renvoie la valeur du coefficient de la case (x, y) de la carte.
On pourra initialiser les coefficients des cases de carte avec 50% de carrés herbus, et pour ceux qui n’ont pas d’herbe on initialisera le coefficient du tableau entre 0 et durée_repousse aléatoirement.
classe Mouton
Attributs
- gain_energie : le gain d’énergie apporté par la consommation d’un carré d’herbe (on peut mettre 4).
- position : couple d’entiers indiquant les coordonnées de la case de la carte occupée par le mouton.
- energie : entier positif (ou nul). Quand l’énergie d’un mouton est à 0, il meurt et l’objet est supprimé. Sera initialisé entre 1 et 2 × gain_energie.
- taux_reproduction : entier compris entre 1 et 100 (on peut mettre 4). Ce taux représente le pourcentage de chance qu’un mouton se reproduise ( par parthénogénèse ici :-)).
Méthodes
variationEnergie(): diminue de 1 l’énergie du mouton s’il n’est pas sur un carré d’herbe, sinon augmente l'énergie de gain_energie . Renvoie la valeur de energie .
Remarque : si plusieurs moutons sont sur la même case herbue, seul le premier bénéficie du gain d’énergie. Réfléchissez bien aux paramètres de cette méthode.deplacement(): le mouton se déplace aléatoirement dans une des huit cases adjacentes de celle où il se trouve.
Il est plus facile de considérer le monde comme dans les jeux vidéo : sortir par le haut de la carte renvoie en bas etc. On peut accepter le fait que le mouton ne se déplace pas à tous les coups, cela simplifie la programmation.
Il y a plusieurs façons de gérer les éventuelles sorties des moutons de la carte, mais la plus astucieuse consiste à utiliser l'opérateur modulo % ( = reste de la division entière ) sur les coordonnées du mouton;
par exemple, que vaut 50 % 50 ? -1 % 50 ? A vous d'utiliser ceci judicieusement !
2. La simulation
Une classe Simulation, comme son nom l’indique, gèrera la simulation.
Attributs :
- nombre_moutons : entier.
- horloge : entier initialisé à 0 au début de la simulation.
- fin_du_monde : entier donnant le "temps" maximum de la simulation.
- moutons : liste d’objets de type
Mouton( il y en a nombre_moutons...) - monde : une instance de la classe
Monde - resultats_herbe : liste construite petit à petit, dont chaque élément est le nombre de carrés d’herbe à chaque "battement d’horloge".
- resultats_moutons : idem mais pour les moutons
Méthode
Une seule méthode, simMouton() gère la simulation en créant une boucle qui remplira plusieurs fonctions les unes après les autres :
- augmente horloge de 1 à chaque appel ;
- fait pousser l’herbe ;
- appelle
variationEnergie()pour chaque mouton. Si l’énergie d’un mouton est nulle, l’instance de celui-ci est supprimée ( suppression de l'élément correspondant dans la liste des moutons ); - Fait se reproduire les moutons. Un nouveau mouton apparaît sur la même case que son parent, avec un "pourcentage de naissance" donné par taux_reproduction.
- Fait se déplacer les moutons.
- Sauvegarde dans resultats_herbe et resultats_moutons les nombres de carrés herbus et de moutons du tour.
On peut arrêter la simulation s’il n’y a plus de moutons, ou s’il y en a plus qu’un nombre fixé (qu’on rajoutera en attribut). Dans ce dernier cas, les moutons ont conquis le monde...
On l’arrête dans tous les cas lorsque l’horloge sonne la fin du monde.
La méthode renvoie les deux listes de résultats.
Pour les tests, mettre fin_du_monde à 10. Réfléchissez aussi si à ce qui peut se passer en ce qui concerne le nombre de moutons d’une génération à la suivante. Les tests peuvent être longs dès que l’on dépasse 100 "battements" d’horloge suivant votre ordinateur.
Pour visualiser les résultats, vous pouvez utiliser le module Matplotlib pour tracer les courbes montrant l'évolution de l'herbe et des moutons au cours du "temps".
3. On rajoute les loups
Les loups "fonctionnent" comme les moutons, sauf qu’ils ne mangent pas d’herbe mais plutôt des moutons...Un loup ne mange qu’un seul mouton par tour.
On peut leur mettre un taux de reproduction de 5, et un gain sur la nourriture de 19. Si le gain est trop petit les loups meurent tous, s’il est trop grand les loups se multiplient trop, et avec les données de naissances la croissance devient exponentielle .
Il est logique de mettre au moins deux fois moins de loups que de moutons. Avec ces données et les précédentes, on obtient un système qui se stabilise.
Il est intéressant de trouver des valeurs initiales qui donnent un système pseudo-périodique (des sortes de sinusoïdes décalées ), ou bien des systèmes chaotiques.
Bonne simulation !