diff --git a/examples/wolf_sheep/wolf_sheep/agents.py b/examples/wolf_sheep/wolf_sheep/agents.py index 6d73e113..688f2509 100644 --- a/examples/wolf_sheep/wolf_sheep/agents.py +++ b/examples/wolf_sheep/wolf_sheep/agents.py @@ -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: @@ -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): @@ -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): diff --git a/examples/wolf_sheep/wolf_sheep/model.py b/examples/wolf_sheep/wolf_sheep/model.py index 48128d00..59f1835c 100644 --- a/examples/wolf_sheep/wolf_sheep/model.py +++ b/examples/wolf_sheep/wolf_sheep/model.py @@ -12,7 +12,6 @@ import mesa from .agents import GrassPatch, Sheep, Wolf -from .scheduler import RandomActivationByTypeFiltered class WolfSheep(mesa.Model): @@ -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." ) @@ -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) ), } ) @@ -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): @@ -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: @@ -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), - ) diff --git a/examples/wolf_sheep/wolf_sheep/scheduler.py b/examples/wolf_sheep/wolf_sheep/scheduler.py deleted file mode 100644 index 97424a55..00000000 --- a/examples/wolf_sheep/wolf_sheep/scheduler.py +++ /dev/null @@ -1,31 +0,0 @@ -from typing import Callable, Optional, Type - -import mesa - - -class RandomActivationByTypeFiltered(mesa.time.RandomActivationByType): - """ - A scheduler that overrides the get_type_count method to allow for filtering - of agents by a function before counting. - - Example: - >>> scheduler = RandomActivationByTypeFiltered(model) - >>> scheduler.get_type_count(AgentA, lambda agent: agent.some_attribute > 10) - """ - - def get_type_count( - self, - type_class: Type[mesa.Agent], - filter_func: Optional[Callable[[mesa.Agent], bool]] = None, - ) -> int: - """ - Returns the current number of agents of certain type in the queue - that satisfy the filter function. - """ - if type_class not in self.agents_by_type: - return 0 - count = 0 - for agent in self.agents_by_type[type_class].values(): - if filter_func is None or filter_func(agent): - count += 1 - return count