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() og Tile.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).