Tutorial: Simpelt økosystem med rovdyr og byttedyr¶
Vi vil nu lave en lille model med AgentsPy. Vi laver en såkaldt predator-prey-model, altså en model med rovdyr og byttedyr.
Start med at lave en ny python-fil, prey.py, og skriv følgende:
from agents import *
model = Model("Predator-prey-model", 50, 50)
run(model)
Dette laver en model med 50x50 felter. Hvis du kører scriptet, bør du få et vindue med en sort firkant.
Vi starter med at lave en Prey
klasse til vores byttedyr. Lav den på følgende måde:
class Prey(Agent):
def setup(self, model):
pass
def step(self, model):
self.direction += randint(-10,10)
self.forward()
Den skal altså ved hvert trin (“step”) ændre sin retning lidt, og bevæge sig fremad.
Lav nu en model_setup
funktion, der “genstarter” modellen og tilføjer 100 nye Prey
agenter:
def model_setup(model):
model.reset()
for a in range(100):
model.add_agent(Prey())
Tilføj så en Setup knap til modellen, der kører model_setup
funktionen:
model.add_button("Setup", model_setup)
Prøv at køre scriptet nu, og se, hvad der sker. Du burde have en Setup knap, der laver 100 agenter, når den klikkes på.
Vi får nu agenterne til at bevæge sig. Tilføj en model_step
funktion, der får byttedyrene til at køre deres egen step
funktion:
def model_step(model):
for a in model.agents:
a.step(model)
Lav nu en Go knap, som kan slås til og fra, og som konstant kører model_step
funktionen, når den er slået til:
model.add_toggle_button("Go", model_step)
Nu har vi vores grundlæggende model. Vi vil nu gøre det muligt for byttedyrene at spise græs, og formere sig, hvis de har spist nok græs.
Vi starter med at tilføje græs. Tilføj i model_setup
:
for t in model.tiles:
t.info["grass"] = True
t.color = (0, 150, 0)
Dette gør sådan, at alle felter starter med at være indikeret som græs. For at de bliver opdateret med en mere “jordlignende” farve, når græsset bliver spist, tilføj følgende i step
:
for t in model.tiles:
if t.info["grass"]:
t.color = (0, 150, 0)
else:
t.color = (80, 80, 0)
if randint(1, 500) == 500:
t.info["grass"] = True
Felter, der har info["grass"] = True
bliver nu farvet grønne, imens dem der har info["grass"] = False
, bliver farvet brune. Felter, der mangler græs, har desuden hvert step en chance for, at deres græs vokser tilbage igen.
Vi gør nu sådan, at byttedyr kan spise græs, formere sig, hvis de spiser nok, og dø, hvis de ikke får nok at spise. Vi laver først funktionaliteten for at spise. Tilføj i Prey
klassens setup
funktion:
self.food = 0
self.time_since_eating = 0
self.color = (100,100,250)
Vi giver dem en blå farve, så vi kan adskille dem fra de rovdyr, vi senere tilføjer.
Tilføj derefter i Prey
klassens step
funktion:
tile = self.current_tile()
if tile.info["grass"]:
self.food += 1
self.time_since_eating = 0
tile.info["grass"] = False
if self.food > 10:
new_prey = Prey()
new_prey.x = self.x
new_prey.y = self.y
model.add_agent(new_prey)
self.food = 0
self.time_since_eating += 1
if self.time_since_eating > 60:
self.destroy()
Her gør byttedyret følgende: * Hvis den står på et felt med græs, spis græsset og læg 1 til “mad-tælleren”. * Hvis den har spist nok græs, lav et nyt byttedyr og sæt “mad-tælleren” til 0. * Hvis der er gået for lang tid siden den sidst har spist, destruerer den sig selv.
Vi vil gerne gøre det muligt at indstille undervejs i modellen, hvor meget græs, et byttedyr skal spise, før det kan formere sig, og hvor lang tid dyret skal gå uden mad, før at det dør.
I model_setup
, tilføj disse to linjer:
model.reproduce_food_count = 10
model.max_time_since_eating = 60
Erstat så følgende linjer i Prey
klassens step
funktion:
if self.food > 10:
...
if self.time_since_eating > 60:
med disse
if self.food > model.reproduce_food_count:
..
if self.time_since_eating > model.max_time_since_eating:
Tilføj så to justerbare sliders ved at indsætte disse to linjer kode, efter at knapperne tilføjes:
model.add_slider("reproduce_food_count", 10, 1, 30)
model.add_slider("max_time_since_eating", 60, 10, 120)
Nu er vores byttedyr færdigt.
Man kan nu, hvis man vil, tilføje rovdyr til simuleringen. Man kan bruge følgende klasse som udgangspunkt:
class Predator(Agent):
def setup(model):
self.size = 15
self.color = (150,0,0)
def step(model):
self.direction += randint(-10,10)
self.forward()
Rovdyret bør have følgende funktionalitet:
- Hvis der er et byttedyr på samme felt som rovdyret, skal det spises (brug en kombination af
Agent.current_tile()
ogTile.get_agents()
til at finde ud af, om der er et byttedyr på samme felt). - Hvis rovdyret har spist nok byttedyr, skal det formere sig (brug samme fremgangsmåde som for byttedyret, der spiser græs).
- Hvis rovdyret ikke har spist noget i lang nok tid, skal det dø (brug også her samme fremgangsmåde som for byttedyret).