From 02339d06b02d2fac607d7eb75ed555508145c76d Mon Sep 17 00:00:00 2001 From: Ewout ter Hoeven Date: Wed, 25 Sep 2024 14:15:09 +0200 Subject: [PATCH] gis: Replace schedulers with AgentSet functionality --- gis/agents_and_networks/src/model/model.py | 13 ++++++------- gis/geo_schelling/model.py | 11 ++++------- .../geo_schelling_points/model.py | 4 +--- gis/population/population/model.py | 4 +--- gis/rainfall/rainfall/model.py | 9 +++------ gis/urban_growth/urban_growth/model.py | 4 +--- 6 files changed, 16 insertions(+), 29 deletions(-) diff --git a/gis/agents_and_networks/src/model/model.py b/gis/agents_and_networks/src/model/model.py index 4aab4219..4ad73499 100644 --- a/gis/agents_and_networks/src/model/model.py +++ b/gis/agents_and_networks/src/model/model.py @@ -22,7 +22,9 @@ def get_time(model) -> pd.Timedelta: def get_num_commuters_by_status(model, status: str) -> int: commuters = [ - commuter for commuter in model.schedule.agents if commuter.status == status + commuter + for commuter in model.agents_by_type[Commuter] + if commuter.status == status ] return len(commuters) @@ -30,11 +32,11 @@ def get_num_commuters_by_status(model, status: str) -> int: def get_total_friendships_by_type(model, friendship_type: str) -> int: if friendship_type == "home": num_friendships = [ - commuter.num_home_friends for commuter in model.schedule.agents + commuter.num_home_friends for commuter in model.agents_by_type[Commuter] ] elif friendship_type == "work": num_friendships = [ - commuter.num_work_friends for commuter in model.schedule.agents + commuter.num_work_friends for commuter in model.agents_by_type[Commuter] ] else: raise ValueError( @@ -45,7 +47,6 @@ def get_total_friendships_by_type(model, friendship_type: str) -> int: class AgentsAndNetworks(mesa.Model): running: bool - schedule: mesa.time.RandomActivation show_walkway: bool show_lakes_and_rivers: bool current_id: int @@ -82,7 +83,6 @@ def __init__( show_driveway=False, ) -> None: super().__init__() - self.schedule = mesa.time.RandomActivation(self) self.show_walkway = show_walkway self.show_lakes_and_rivers = show_lakes_and_rivers self.data_crs = data_crs @@ -144,7 +144,6 @@ def _create_commuters(self) -> None: commuter.set_work(random_work) commuter.status = "home" self.space.add_commuter(commuter) - self.schedule.add(commuter) def _load_buildings_from_file( self, buildings_file: str, crs: str, campus: str @@ -215,7 +214,7 @@ def _set_building_entrance(self) -> None: def step(self) -> None: self.__update_clock() - self.schedule.step() + self.agents.shuffle_do("step") self.datacollector.collect(self) def __update_clock(self) -> None: diff --git a/gis/geo_schelling/model.py b/gis/geo_schelling/model.py index 159e7317..81568fc2 100644 --- a/gis/geo_schelling/model.py +++ b/gis/geo_schelling/model.py @@ -55,12 +55,11 @@ def step(self): if similar < different: # Select an empty region empties = [a for a in self.model.space.agents if a.atype is None] - # Switch atypes and add/remove from scheduler + # Switch atypes new_region = random.choice(empties) new_region.atype = self.atype - self.model.schedule.add(new_region) self.atype = None - self.model.schedule.remove(self) + self.remove() else: self.model.happy += 1 @@ -77,7 +76,6 @@ def __init__(self, density=0.6, minority_pc=0.2, export_data=False): self.minority_pc = minority_pc self.export_data = export_data - self.schedule = mesa.time.RandomActivation(self) self.space = mg.GeoSpace(warn_crs_conversion=False) self.happy = 0 @@ -100,7 +98,6 @@ def __init__(self, density=0.6, minority_pc=0.2, export_data=False): agent.atype = 1 else: agent.atype = 0 - self.schedule.add(agent) def export_agents_to_file(self) -> None: self.space.get_agents_as_GeoDataFrame(agent_cls=SchellingAgent).to_crs( @@ -113,10 +110,10 @@ def step(self): If All agents are happy, halt the model. """ self.happy = 0 # Reset counter of happy agents - self.schedule.step() + self.agents.shuffle_do("step") self.datacollector.collect(self) - if self.happy == self.schedule.get_agent_count(): + if self.happy == len(self.agents): self.running = False if not self.running and self.export_data: diff --git a/gis/geo_schelling_points/geo_schelling_points/model.py b/gis/geo_schelling_points/geo_schelling_points/model.py index 6716b17b..91da59f1 100644 --- a/gis/geo_schelling_points/geo_schelling_points/model.py +++ b/gis/geo_schelling_points/geo_schelling_points/model.py @@ -17,7 +17,6 @@ def __init__(self, red_percentage=0.5, similarity_threshold=0.5): self.red_percentage = red_percentage PersonAgent.SIMILARITY_THRESHOLD = similarity_threshold - self.schedule = mesa.time.RandomActivation(self) self.space = Nuts2Eu() self.datacollector = mesa.DataCollector( @@ -40,7 +39,6 @@ def __init__(self, red_percentage=0.5, similarity_threshold=0.5): region_id=region.unique_id, ) self.space.add_person_to_region(person, region_id=region.unique_id) - self.schedule.add(person) self.datacollector.collect(self) @@ -57,7 +55,7 @@ def happy(self): return self.space.num_people - self.unhappy def step(self): - self.schedule.step() + self.agents.shuffle_do("step") self.datacollector.collect(self) if not self.unhappy: diff --git a/gis/population/population/model.py b/gis/population/population/model.py index 5ab9001c..61b8775b 100644 --- a/gis/population/population/model.py +++ b/gis/population/population/model.py @@ -70,7 +70,6 @@ def __init__( Person.MOBILITY_RANGE_X = pixel_size_x / 2.0 Person.MOBILITY_RANGE_Y = pixel_size_y / 2.0 - self.schedule = mesa.time.RandomActivation(self) self._create_agents() def _create_agents(self): @@ -90,7 +89,6 @@ def _create_agents(self): ) person.set_random_world_coord() self.space.add_agents(person) - self.schedule.add(person) def step(self): - self.schedule.step() + self.agents.shuffle_do("step") diff --git a/gis/rainfall/rainfall/model.py b/gis/rainfall/rainfall/model.py index 21931c49..5ec81c81 100644 --- a/gis/rainfall/rainfall/model.py +++ b/gis/rainfall/rainfall/model.py @@ -44,7 +44,7 @@ def pos(self, pos): def step(self): if self.is_at_boundary: - self.model.schedule.remove(self) + self.remove() else: lowest_pos = min( self.model.space.raster_layer.get_neighboring_cells( @@ -65,7 +65,6 @@ def __init__(self, rain_rate=500, water_height=5, export_data=False, num_steps=2 self.num_steps = num_steps self.space = CraterLake(crs="epsg:4326", water_height=water_height, model=self) - self.schedule = mesa.time.RandomActivation(self) self.datacollector = mesa.DataCollector( { "Total Amount of Water": "water_amount", @@ -101,10 +100,9 @@ def step(self): pos=(random_x, random_y), ) self.space.add_raindrop(raindrop) - self.schedule.add(raindrop) self.water_amount += 1 - self.schedule.step() + self.agents.shuffle_do("step") self.datacollector.collect(self) current_water_level = self.space.raster_layer.get_raster("water_level") @@ -113,8 +111,7 @@ def step(self): "water_level_normalized", ) - self.num_steps -= 1 - if self.num_steps == 0: + if self.steps >= self.num_steps: self.running = False if not self.running and self.export_data: self.export_water_level_to_file() diff --git a/gis/urban_growth/urban_growth/model.py b/gis/urban_growth/urban_growth/model.py index 98a530b4..24d71017 100644 --- a/gis/urban_growth/urban_growth/model.py +++ b/gis/urban_growth/urban_growth/model.py @@ -33,7 +33,6 @@ def __init__( self.slope_coefficient = slope_coefficient self.critical_slope = critical_slope self.road_influence = road_influence - self.schedule = mesa.time.RandomActivation(self) self.dispersion_value = (dispersion_coefficient * 0.005) * ( world_width**2 + world_height**2 @@ -52,7 +51,6 @@ def __init__( cell.road_found = False cell.road_pixel = None cell.model = self - self.schedule.add(cell) self.initialize_data_collector( model_reporters={"Percentage Urbanized": "pct_urbanized"} @@ -110,7 +108,7 @@ def _check_suitability(self) -> None: def step(self): self._spontaneous_growth() - self.schedule.step() + self.agents.shuffle_do("step") if self.road_influence: self._road_influenced_growth() self.datacollector.collect(self)