Skip to content

Commit

Permalink
wolf_sheep: Replace custom scheduler with AgentSet functionality
Browse files Browse the repository at this point in the history
This resolves all warnings outputted by this model.

For the model step, the behavior of the old RandomActivationByType scheduler when using step(shuffle_types=True, shuffle_agents=True) is replicated. Conceptually, it can be argued that this should be modelled differently.

The verbose prints are also removed.
  • Loading branch information
EwoutH committed Aug 12, 2024
1 parent fbf80af commit 4dac7dc
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 74 deletions.
8 changes: 3 additions & 5 deletions examples/wolf_sheep/wolf_sheep/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def step(self):
# Death
if self.energy < 0:
self.model.grid.remove_agent(self)
self.model.schedule.remove(self)
self.remove()
living = False

if living and self.random.random() < self.model.sheep_reproduce:
Expand All @@ -46,7 +46,6 @@ def step(self):
self.energy /= 2
lamb = Sheep(self.model.next_id(), self.model, self.moore, self.energy)
self.model.grid.place_agent(lamb, self.pos)
self.model.schedule.add(lamb)


class Wolf(RandomWalker):
Expand Down Expand Up @@ -74,19 +73,18 @@ def step(self):

# Kill the sheep
self.model.grid.remove_agent(sheep_to_eat)
self.model.schedule.remove(sheep_to_eat)
sheep_to_eat.remove()

# Death or reproduction
if self.energy < 0:
self.model.grid.remove_agent(self)
self.model.schedule.remove(self)
self.remove()
else:
if self.random.random() < self.model.wolf_reproduce:
# Create a new wolf cub
self.energy /= 2
cub = Wolf(self.model.next_id(), self.model, self.moore, self.energy)
self.model.grid.place_agent(cub, self.pos)
self.model.schedule.add(cub)


class GrassPatch(mesa.Agent):
Expand Down
49 changes: 11 additions & 38 deletions examples/wolf_sheep/wolf_sheep/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import mesa

from .agents import GrassPatch, Sheep, Wolf
from .scheduler import RandomActivationByTypeFiltered


class WolfSheep(mesa.Model):
Expand All @@ -35,8 +34,6 @@ class WolfSheep(mesa.Model):
grass_regrowth_time = 30
sheep_gain_from_food = 4

verbose = False # Print-monitoring

description = (
"A model for simulating wolf and sheep (predator-prey) ecosystem modelling."
)
Expand Down Expand Up @@ -81,14 +78,13 @@ def __init__(
self.grass_regrowth_time = grass_regrowth_time
self.sheep_gain_from_food = sheep_gain_from_food

self.schedule = RandomActivationByTypeFiltered(self)
self.grid = mesa.space.MultiGrid(self.width, self.height, torus=True)
self.datacollector = mesa.DataCollector(
{
"Wolves": lambda m: m.schedule.get_type_count(Wolf),
"Sheep": lambda m: m.schedule.get_type_count(Sheep),
"Grass": lambda m: m.schedule.get_type_count(
GrassPatch, lambda x: x.fully_grown
"Wolves": lambda m: len(m.get_agents_of_type(Wolf)),
"Sheep": lambda m: len(m.get_agents_of_type(Sheep)),
"Grass": lambda m: len(
m.get_agents_of_type(GrassPatch).select(lambda a: a.fully_grown)
),
}
)
Expand All @@ -100,7 +96,6 @@ def __init__(
energy = self.random.randrange(2 * self.sheep_gain_from_food)
sheep = Sheep(self.next_id(), self, True, energy)
self.grid.place_agent(sheep, (x, y))
self.schedule.add(sheep)

# Create wolves
for i in range(self.initial_wolves):
Expand All @@ -109,7 +104,6 @@ def __init__(
energy = self.random.randrange(2 * self.wolf_gain_from_food)
wolf = Wolf(self.next_id(), self, True, energy)
self.grid.place_agent(wolf, (x, y))
self.schedule.add(wolf)

# Create grass patches
if self.grass:
Expand All @@ -123,42 +117,21 @@ def __init__(

patch = GrassPatch(self.next_id(), self, fully_grown, countdown)
self.grid.place_agent(patch, (x, y))
self.schedule.add(patch)

self.running = True
self.datacollector.collect(self)

def step(self):
self.schedule.step()
# This replicated the behavior of the old RandomActivationByType scheduler
# when using step(shuffle_types=True, shuffle_agents=True).
# Conceptually, it can be argued that this should be modelled differently.
self.random.shuffle(self.agent_types)
for agent_type in self.agent_types:
self.get_agents_of_type(agent_type).do("step")

# collect data
self.datacollector.collect(self)
if self.verbose:
print(
[
self.schedule.time,
self.schedule.get_type_count(Wolf),
self.schedule.get_type_count(Sheep),
self.schedule.get_type_count(GrassPatch, lambda x: x.fully_grown),
]
)

def run_model(self, step_count=200):
if self.verbose:
print("Initial number wolves: ", self.schedule.get_type_count(Wolf))
print("Initial number sheep: ", self.schedule.get_type_count(Sheep))
print(
"Initial number grass: ",
self.schedule.get_type_count(GrassPatch, lambda x: x.fully_grown),
)

for i in range(step_count):
self.step()

if self.verbose:
print("")
print("Final number wolves: ", self.schedule.get_type_count(Wolf))
print("Final number sheep: ", self.schedule.get_type_count(Sheep))
print(
"Final number grass: ",
self.schedule.get_type_count(GrassPatch, lambda x: x.fully_grown),
)
31 changes: 0 additions & 31 deletions examples/wolf_sheep/wolf_sheep/scheduler.py

This file was deleted.

0 comments on commit 4dac7dc

Please sign in to comment.