def __init__(self, density, minority_pc): self.density = density self.minority_pc = minority_pc self.schedule = RandomActivation(self) self.grid = GeoSpace() self.happy = 0 self.datacollector = DataCollector({"happy": "happy"}) self.running = True # Set up the grid with patches for every NUTS region AC = AgentCreator(SchellingAgent, {"model": self}) agents = AC.from_file("nuts_rg_60M_2013_lvl_2.geojson") self.grid.add_agents(agents) # Set up agents for agent in agents: if random.random() < self.density: if random.random() < self.minority_pc: agent.atype = 1 else: agent.atype = 0 self.schedule.add(agent)
def __init__(self, density, minority_pc): self.density = density self.minority_pc = minority_pc self.schedule = RandomActivation(self) self.grid = GeoSpace(crs='epsg:4326') self.happy = 0 self.datacollector = DataCollector( {"happy": lambda m: m.happy}) # Model-level count of happy agents self.running = True # Set up the grid with patches for every NUTS region regions = geojson.load(open('nuts_rg_60M_2013_lvl_2.geojson')) self.grid.create_agents_from_GeoJSON(regions, SchellingAgent, model=self, unique_id='NUTS_ID') # Set up agents for agent in self.grid.agents: if random.random() < self.density: if random.random() < self.minority_pc: agent.atype = 1 else: agent.atype = 0 self.schedule.add(agent) # Update the bounding box of the grid and create a new rtree self.grid.update_bbox() self.grid.create_rtree()
def __init__(self, agent_class, num_col_left, num_col_mid, num_col_right, num_row, dist_bw_seats, num_infected, breath_prob, cough_prob, sneeze_prob, breath_dist, cough_dist, sneeze_dist, prob_infected): # mesa required attributes self.running = True self.grid = GeoSpace() self.schedule = BaseScheduler( self ) # scheduler dictates model level agent behavior, aka. step function # variables used for later functions that need descriptions of the model dim_bus = [num_col_left, num_col_mid, num_col_right, num_row] self.max_columns = (dim_bus[0] + dim_bus[1] + dim_bus[2]) * dist_bw_seats self.max_rows = dim_bus[3] * dist_bw_seats self.seat_dist = dist_bw_seats i = 1 for x in range(0, dim_bus[0] * dist_bw_seats, dist_bw_seats): for y in range(0, dim_bus[3] * dist_bw_seats, dist_bw_seats): pnt = Point(x, y) i += 1 a = agent_class(model=self, shape=pnt, unique_id="na" + str(i), breath_prob=breath_prob, cough_prob=cough_prob, sneeze_prob=sneeze_prob, breath_dist=breath_dist, cough_dist=cough_dist, sneeze_dist=sneeze_dist, prob_infected=prob_infected) self.grid.add_agents(a) self.schedule.add(a) for x in range((dim_bus[0] + dim_bus[1]) * dist_bw_seats, (dim_bus[0] + dim_bus[1] + dim_bus[2]) * dist_bw_seats, dist_bw_seats): for y in range(0, dim_bus[3] * dist_bw_seats, dist_bw_seats): pnt = Point(x, y) i += 1 a = agent_class(model=self, shape=pnt, unique_id="na" + str(i), breath_prob=breath_prob, cough_prob=cough_prob, sneeze_prob=sneeze_prob, breath_dist=breath_dist, cough_dist=cough_dist, sneeze_dist=sneeze_dist, prob_infected=prob_infected) self.grid.add_agents(a) self.schedule.add(a) infected_agents = random.sample(self.grid.agents, num_infected) for i in infected_agents: i.infected = True
def __init__(self, num_bikes=10): self.grid = GeoSpace() self.num_bikes = 10 road_agent_kwargs = dict(model=self) AC = AgentCreator(agent_class=Road, agent_kwargs=road_agent_kwargs) # agents = AC.from_GeoJSON(GeoJSON=geojson_roads, unique_id="osm_id") agents = AC.from_file("roads.geojson") print(agents[0].shape) self.grid.add_agents(agents) self.datacollector = DataCollector() self.running = True self.schedule = RandomActivation(self)
class SchellingModel(Model): """Model class for the Schelling segregation model.""" def __init__(self, density, minority_pc): self.density = density self.minority_pc = minority_pc self.schedule = RandomActivation(self) self.grid = GeoSpace() self.happy = 0 self.datacollector = DataCollector({"happy": "happy"}) self.running = True # Set up the grid with patches for every NUTS region AC = AgentCreator(SchellingAgent, {"model": self}) agents = AC.from_file("nuts_rg_60M_2013_lvl_2.geojson") self.grid.add_agents(agents) # Set up agents for agent in agents: if random.random() < self.density: if random.random() < self.minority_pc: agent.atype = 1 else: agent.atype = 0 self.schedule.add(agent) def step(self): """Run one step of the model. If All agents are happy, halt the model. """ self.happy = 0 # Reset counter of happy agents self.schedule.step() # self.datacollector.collect(self) if self.happy == self.schedule.get_agent_count(): self.running = False
class SchellingModel(Model): """Model class for the Schelling segregation model.""" def __init__(self, density, minority_pc): self.density = density self.minority_pc = minority_pc self.schedule = RandomActivation(self) self.grid = GeoSpace(crs='epsg:4326') self.happy = 0 self.datacollector = DataCollector( {"happy": lambda m: m.happy}) # Model-level count of happy agents self.running = True # Set up the grid with patches for every NUTS region regions = geojson.load(open('nuts_rg_60M_2013_lvl_2.geojson')) self.grid.create_agents_from_GeoJSON(regions, SchellingAgent, model=self, unique_id='NUTS_ID') # Set up agents for agent in self.grid.agents: if random.random() < self.density: if random.random() < self.minority_pc: agent.atype = 1 else: agent.atype = 0 self.schedule.add(agent) # Update the bounding box of the grid and create a new rtree self.grid.update_bbox() self.grid.create_rtree() def step(self): """Run one step of the model. If All agents are happy, halt the model. """ self.happy = 0 # Reset counter of happy agents self.schedule.step() self.datacollector.collect(self) if self.happy == self.schedule.get_agent_count(): self.running = False self.grid.create_rtree()
class GeoModel(Model): def __init__(self, num_bikes=10): self.grid = GeoSpace() self.num_bikes = 10 road_agent_kwargs = dict(model=self) AC = AgentCreator(agent_class=Road, agent_kwargs=road_agent_kwargs) # agents = AC.from_GeoJSON(GeoJSON=geojson_roads, unique_id="osm_id") agents = AC.from_file("roads.geojson") print(agents[0].shape) self.grid.add_agents(agents) self.datacollector = DataCollector() self.running = True self.schedule = RandomActivation(self) def step(self): """Run one step of the model. If All agents are happy, halt the model. """ self.schedule.step() self.datacollector.collect(self)
def __init__(self, locations, N1, scheduleClass, initialization=None, seed=None): if initialization == None: raise Exception("Initialization cannot be none") N = len(locations['features'] ) * N1 #N1 =density of housholds in one building #print(N) self.landuse = locations['features'][0]['landuse'] #print(self.landuse[0]) self.running = True self.num_agents = N self.schedule = scheduleClass(self) self.G = nx.complete_graph(self.num_agents) self.nw = NetworkGrid(self.G) self.grid = GeoSpace(crs='epsg:4326') agent_kwargs = dict(model=self, unique_id='id') self.grid.create_agents_from_GeoJSON(locations, agent=LocationAgent, **agent_kwargs) self.locations = list(self.grid.agents) self.initialize(initialization) self.datacollector = DataCollector( agent_reporters={ "NewShape": agent_loc, "Satisfaction": agent_satisfaction, "LandUse": agent_LU, "H**o": agent_homo, "WorkPlace": agent_workplace }) self.grid.update_bbox() self.grid.create_rtree()
class InsiteModel(Model): """A model with some number of agents.""" def __init__(self, cit_pd, stakeholder_pd, regulator_pd, geojson_list, meta_data, neighbor_type=0, efficiency_parameter=1.5, log_level=0): self.log_level = log_level # * Default values # List of citizen self.cit_list: List[CitAgent] = [] self.cbo_list = [] # List of cits' CBOs # List of those who can negotiate with stakeholder self.sh_negotiator_list = [] # List of CBOs created after negotiating with stakeholder self.sh_in_coalition_list = [] # Can includes cits or stakeholder # Strictly regulator self.regulator_negotiator_list = [] self.regulator_in_coalition_list: List[RegulatorAgent] = [] # For performance issue # we use dict for fast lookup and modification self.agent_dict: Dict[str, All_Agent_Type] = {} # List of stakeholder and regulator from csv file self.sh_list: List[StakeholderAgent] = [] self.regulator_list: List[RegulatorAgent] = [] # Big-NGO and Utility-info self.need: float = 0 self.procedure: float = 0 # Otherb self.is_regulator_anti: bool = False # * Store all the dataframe for later use self.cit_pd = cit_pd self.stakeholder_pd = stakeholder_pd self.regulator_pd = regulator_pd self.print_log(2, "Initializing model") # * Initialize mesa self.grid = GeoSpace(crs={"init": "epsg:4326"}) self.schedule = BaseScheduler(self) self.talk_span: float = meta_data['talk_span'] self.total_cit: int = meta_data['actual_num_cit'] self.disruption: float = meta_data['disruption'] self.need: float = meta_data['need'] self.NGO_message: float = meta_data['NGO_message'] self.procedure: float = meta_data['procedure'] self.sponsor_message: float = meta_data['sponsor_message'] self.neighbor_type: int = neighbor_type self.efficiency_parameter: float = efficiency_parameter # * Initialize citizens self.print_log(2, "Initializing citizens") self.setup_cit(geojson_list) # * Initialize data collectors self.print_log(2, "Initializing data collectors") # Set up data collector self.datacollector = DataCollector(model_reporters={ "Total preference": ModelCalculator.compute_total("pref"), "Total power": ModelCalculator.compute_total("power"), }, agent_reporters={ "Preference": "pref", "Power": "power", }) self.sh_collector: CustomAgentDataCollector = CustomAgentDataCollector( model_reporters={ "Total sh preference": ModelCalculator.compute_total("sh_pref"), }, agent_reporters={ "Stakeholder preference": "sh_pref", }, agent_list=self.sh_list) self.regulator_collector: CustomAgentDataCollector = CustomAgentDataCollector( model_reporters={ "Total regulator preference": ModelCalculator.compute_total("regulator_pref"), }, agent_reporters={ "Regulator preference": "regulator_pref", }, agent_list=self.regulator_list) def step(self): cur_tick = self.schedule.steps self.print_log(1, f"---STARTING tick {cur_tick}") '''Order''' # Cit will send messages starting from tick 0 # Stakeholder will send messages starting from tick 1 # with whoever in stakeholder negotiator list # Regulator will send messages starting from tick 15 # with whoever in stakeholder negotiator list # Regulator will talk among themself starting from tick 21 # * 1. Cits talking if cur_tick <= 20: # ******** Forming citizen coalition self.send_cit_messages() # Turtle-talk # * 2. Regulator and stakeholder setup if cur_tick == 1: self.setup_stakeholder() # Stakeholder-setup if cur_tick > 1: self.update_stakeholder_pre_tick() # Stakeholder-setup 2 if cur_tick == 15: self.setup_regulator() # Regulator-setup if cur_tick > 15: self.update_regulator_pre_tick() # Regulator-setup 2 # * 3. Regulator and stakeholder talking if cur_tick <= 20 and cur_tick >= 1: # ******** Forming sh coalition self.send_sh_messages() # Stakeholder-talk if cur_tick >= 21: self.send_regulator_messages() # Regulator-talk # * Post tick update if cur_tick >= 1: # ******** Utility and Big-NGO self.communicate_sponsor_risk() # Utility-info self.communicate_big_ngo_risk() # Big-NGO self.merge_cbo() if cur_tick == 25: self.start_regulator_vote() self.execute_influence_model() self.execute_label_up() # ******** Advance the model by one step self.print_log(2, "Agents start stepping") self.schedule.step() # ******** Collect stats self.print_log(2, "Collecting data") self.datacollector.collect(self) self.sh_collector.collect(cur_tick) self.regulator_collector.collect(cur_tick) self.print_log(1, f"---ENDING tick {cur_tick}\n") # # '''------Main Methods------''' # * Cit stuff def setup_cit(self, geojson_list): # --- Create citizens for cit_attr in self.cit_pd.to_dict(orient='records'): # * Citizen # ? Should we leave this here if cit_attr['proximity'] > 1: continue # Extract the geojson of that agent shape = Polygon(geojson_list[str( cit_attr['id'])]['coordinates'][0]) attr_list = cit_attr.copy() # Make a copy to avoid side-effect attr_list['disruption'] = self.disruption attr_list['NGO_message'] = self.NGO_message attr_list['sponsor_message'] = self.sponsor_message attr_list['efficiency_parameter'] = self.efficiency_parameter # Then create an agent out of those agent = CitAgent(self, attr_list, shape) self.grid.add_agents(agent) self.schedule.add(agent) self.cit_list.append(agent) # Add the reference to that agent self.agent_dict[cit_attr['id']] = agent def send_cit_messages(self): # ******** Forming citizen coalition self.print_log(2, "Sending cit messages STARTS") coalition_helper = CoalitionHelper("unique_id", "power", "own_pref", "utility", self.efficiency_parameter, log_level=self.log_level) # * Trying to form all coalitions # and ignore the one who is already in CBO potential_coalition_list = coalition_helper.form_coalition( self.get_neighbor_dispatcher(self.neighbor_type), agent_list=self.cit_list, ignored_list=self.cbo_list) self.print_log(3, "List of all cits coalition: ", potential_coalition_list) # * Update the cit coalition of all eligible agent for coalition in potential_coalition_list: agent_1 = self.agent_dict[coalition['id_1']] agent_2 = self.agent_dict[coalition['id_2']] # Make sure this is a citizen assert isinstance(agent_1, CitAgent) assert isinstance(agent_2, CitAgent) agent_1.update_cit_coalition_attrs(coalition) agent_2.update_cit_coalition_attrs(coalition) self.cbo_list.append(agent_1) self.cbo_list.append(agent_2) # Always add only agent 1 as sh self.sh_negotiator_list.append(agent_1) self.print_log(2, "Sending cit messages ENDS") def communicate_sponsor_risk(self): # Formerly utility-info counter = 0 sum_pref = 0 for stakeholder in self.sh_list: if stakeholder.is_sponsor: counter += 1 sum_pref += stakeholder.sh_pref for cit in self.cit_list: cit.communicate_sponsor_risk(self.need, sum_pref / counter) def communicate_big_ngo_risk(self): # Formerly big-NGO counter = 0 sum_pref = 0 for stakeholder in self.sh_list: if stakeholder.is_big_ngo: counter += 1 sum_pref += stakeholder.sh_pref for cit in self.cit_list: cit.communicate_big_ngo_risk(self.procedure, sum_pref / counter) def execute_influence_model(self): for cits in self.cit_list: cits.execute_influence_model() def execute_label_up(self): for cits in self.cit_list: cits.execute_label_up() # * Stakeholder stuff def setup_stakeholder(self): # --- Create stakeholders # First find the sum power of all cit sum_power = 0 for cit in self.cit_list: sum_power += cit.power # Then create stakeholder based on that for sh_attr in self.stakeholder_pd.to_dict(orient='records'): attr_list = sh_attr.copy() # Make a copy to avoid side-effect # Then create an agent out of those agent = StakeholderAgent(self, attr_list, cit_power=sum_power) # self.schedule.add(agent) # ! Double check this self.sh_negotiator_list.append(agent) self.sh_list.append(agent) # Add the reference to that agent self.agent_dict[sh_attr['id']] = agent def update_stakeholder_pre_tick(self): pass def send_sh_messages(self): # ******** Forming sh coalition self.print_log(2, "Sending stakeholder messages STARTS") coalition_helper = CoalitionHelper("unique_id", "sh_power", "sh_pref", "sh_utility", self.efficiency_parameter, log_level=self.log_level) # * Trying to form all coalitions # and ignore the one who is already in CBO potential_coalition_list = coalition_helper.form_coalition( self.get_neighbor_dispatcher(0), # Always get all neighbors agent_list=self.sh_negotiator_list, ignored_list=self.sh_in_coalition_list) self.print_log(3, "List of all sh coalition: ", potential_coalition_list) # * Update the stakeholder coalition of all eligible agent for coalition in potential_coalition_list: agent_1 = self.agent_dict[coalition['id_1']] agent_2 = self.agent_dict[coalition['id_2']] # Make sure this is a citizen or stakeholder assert isinstance(agent_1, (StakeholderAgent, CitAgent, RegulatorAgent)) assert isinstance(agent_2, (StakeholderAgent, CitAgent, RegulatorAgent)) agent_1.update_sh_coalition_attrs(coalition) agent_2.update_sh_coalition_attrs(coalition) self.sh_in_coalition_list.append(agent_1) self.sh_in_coalition_list.append(agent_2) self.print_log(2, "Sending stakeholder messages ENDS") # * Regulator stuff def setup_regulator(self): # --- Create stakeholders # First find the sum power of all cit sum_power = 0 for stakeholder in self.sh_negotiator_list: sum_power += stakeholder.sh_power # Then create stakeholder based on that for regulator_attr in self.regulator_pd.to_dict(orient='records'): # Make a copy to avoid side-effect attr_list = regulator_attr.copy() # Then create an agent out of those agent = RegulatorAgent(self, attr_list, sh_power=sum_power) # self.schedule.add(agent) # ! Double check this self.regulator_list.append(agent) self.regulator_negotiator_list.append(agent) # Also negotiate with other stakeholders self.sh_negotiator_list.append(agent) # Add the reference to that agent self.agent_dict[regulator_attr['id']] = agent def update_regulator_pre_tick(self): pass def send_regulator_messages(self): # ******** Forming regulator coalition self.print_log(2, "Sending regluator messages STARTS") coalition_helper = CoalitionHelper("unique_id", "regulator_power", "regulator_pref", "regulator_utility", self.efficiency_parameter, log_level=self.log_level) # * Trying to form all coalitions # and ignore the one who is already in CBO potential_regulator_coalition_list = coalition_helper.form_coalition( self.get_neighbor_dispatcher(0), # Always get all neighbors agent_list=self.regulator_negotiator_list, ignored_list=self.regulator_in_coalition_list) self.print_log(3, "List of all regulator coalition: ", potential_regulator_coalition_list) # * Update the regulator coalition of all eligible agent for coalition in potential_regulator_coalition_list: agent_1 = self.agent_dict[coalition['id_1']] agent_2 = self.agent_dict[coalition['id_2']] # Make sure this is a regulator assert isinstance(agent_1, RegulatorAgent) assert isinstance(agent_2, RegulatorAgent) agent_1.update_regulator_coalition_attrs(coalition) agent_2.update_regulator_coalition_attrs(coalition) self.regulator_in_coalition_list.append(agent_1) self.regulator_in_coalition_list.append(agent_2) self.print_log(2, "Sending regulator messages ENDS") # * Others def merge_cbo(self): # ? Used for later displaying if self.schedule.steps == 1: pass elif self.schedule.steps <= 20: if self.schedule.steps == 20: # Halt cit in cbo pass else: pass def start_regulator_vote(self): num_regulator_anti = 0 num_regulator_pro = 0 for regulator in self.regulator_list: if regulator.regulator_pref <= 50: num_regulator_pro += 1 else: num_regulator_anti if num_regulator_pro <= num_regulator_anti: self.is_regulator_anti = True # # '''------Helpers------''' # Loggings def print_log(self, log_level, log_string, json_data=None): if self.log_level >= log_level: print(log_string, flush=True) if json_data is not None: pp = pprint.PrettyPrinter(indent=2) pp.pprint(json_data) # Neighbor issues... # Helper to trieve neighbor list of an agent def get_neighbor_dispatcher(self, neighbor_type): """Generate list of neighbor of the "agent" Args: agent_list ([list]): list of agent to check agent ([object]): current agent neighbor_type ([int]): type of neightbor to get for each cit 0: treats all cits as neighbor 1: direct neighbor 2: small world network # TODO 3: talk span in km (default: {0}) """ if neighbor_type == 0: return self.get_all_as_neighbors if neighbor_type == 1: return self.get_direct_neighbors if neighbor_type == 3: return self.get_neighbors_within_talk_span def get_all_as_neighbors(self, _, agent_list): # Make a copy of the agent list return agent_list[:] def get_direct_neighbors(self, agent, _): # Get the direct neighbor of the specified agent potential_neighbors = self.grid.get_neighbors(agent) return potential_neighbors def get_neighbors_within_talk_span(self, agent, agent_list): result = [] agent_center = agent.shape.centroid # Reverse tuple for lat long agent_coords = list(agent_center.coords)[0][::-1] for other in agent_list: if agent is other or other: continue other_center = other.shape.centroid other_coords = list(other_center.coords)[0][::-1] coord_distance = distance.distance(agent_coords, other_coords).km if coord_distance < self.talk_span: result.append(other) return result
class InfectedModel(Model): """Model class for a simplistic infection model.""" # Geographical parameters for desired map MAP_COORDS = COORDS[CITY] unique_id = "NAME" def __init__(self, monitored_statistic, show_schools, show_restaurants): """ Create a new InfectedModel """ self.schedule = BaseScheduler(self) self.grid = GeoSpace() self.steps = 0 self.counts = None self.reset_counts() self.monitored_statistic = 'infected-per-home-series' self.show_schools = show_schools self.show_restaurants = show_restaurants self.maximum = {self.monitored_statistic: 0} self.minimum = {self.monitored_statistic: sys.maxsize} with open(LOG_FILE) as json_file: self.simulation_data = json.load(json_file) #for key in self.simulation_data[self.monitored_statistic]: # for v in self.simulation_data[self.monitored_statistic][key]: # if v > self.maximum[self.monitored_statistic]: self.maximum[self.monitored_statistic] = v # if v < self.minimum[self.monitored_statistic]: self.minimum[self.monitored_statistic] = v self.minimum['infected-per-home-series'] = 0 self.maximum['infected-per-home-series'] = 500 self.running = True self.datacollector = DataCollector({ "infected": get_infected_count, "susceptible": get_susceptible_count, "recovered": get_recovered_count, "dead": get_dead_count, }) # Neighboorhoods AC = AgentCreator(NeighbourhoodAgent, {"model": self}) neighbourhood_agents = AC.from_file(geojson_neighborhoods, unique_id=self.unique_id) for agent in neighbourhood_agents: for neighborhood in NEIGHBORHOODS['features']: if agent.unique_id == neighborhood['properties']['NAME']: agent2feature[agent.unique_id] = neighborhood break self.grid.add_agents(neighbourhood_agents) # Schools AC = AgentCreator(SchoolAgent, {"model": self}) school_agents = AC.from_file(geojson_schools, unique_id=self.unique_id) for agent in school_agents: for school in SCHOOLS['features']: if agent.unique_id == school['properties']['NAME']: agent2feature[agent.unique_id] = school break self.grid.add_agents(school_agents) # Restaurants AC = AgentCreator(RestaurantAgent, {"model": self}) restaurant_agents = AC.from_file(geojson_restaurants, unique_id=self.unique_id) for agent in restaurant_agents: for restaurant in RESTAURANTS['features']: if agent.unique_id == restaurant['properties']['NAME']: agent2feature[agent.unique_id] = restaurant break self.grid.add_agents(restaurant_agents) for agent in neighbourhood_agents + school_agents: self.schedule.add(agent) self.datacollector.collect(self) def reset_counts(self): self.counts = { "susceptible": 0, "infected": 0, "recovered": 0, "dead": 0, "safe": 0, "hotspot": 0, } def step(self): #if self.steps >= len(self.simulation_data['infected-series']) - 2: if self.steps > 50: self.running = False return self.steps += 1 self.reset_counts() self.schedule.step() self.grid._recreate_rtree( ) # Recalculate spatial tree, because agents are moving self.datacollector.collect(self) return True
def __init__(self, map_path, schedule_path, grade_N, KG_N, preschool_N, special_education_N, faculty_N, seat_dist, init_patient=3, attend_rate=1, mask_prob=0.516, inclass_lunch=False, username="******"): # zipcode etc, for access of more realistic population from KG perhaps # model param init self.__mask_prob = mask_prob self.inclass_lunch = inclass_lunch self.seat_dist = math.ceil(seat_dist / (attend_rate**(1 / 2))) self.idle_teachers = [] # teachers to be assigned without a classroom self.init_patient = init_patient # mesa model init self.running = True self.grid = GeoSpace() self.schedule = BaseScheduler(self) #data collect init model_reporters = { "day": "day_count", "cov_positive": "infected_count" } agent_reporters = { "unique_id": "unique_id", "health_status": "health_status", "symptoms": "symptoms", "x": "x", "y": "y", "viral_load": "viral_load" } self.datacollector = datacollection.DataCollector( model_reporters=model_reporters, agent_reporters=agent_reporters) school_gdf = load_map(map_path) # room agent init self.room_agents = school_gdf.apply( lambda x: Classroom(unique_id=x["Id"], model=self, shape=x["geometry"], room_type=x["room_type"]), axis=1).tolist() self.grid.add_agents(self.room_agents) # stats tracking init self.infected_count = 0 self.step_count = 0 self.day_count = 0 self.num_exposed = 0 # student activity init self.schoolday_schedule = pd.read_csv(schedule_path) self.activity = None # id tracking init self.__teacher_id = 0 self.__student_id = 0 self.__faculty_N = faculty_N self.schedule_ids = self.schoolday_schedule.columns self.recess_yards = find_room_type(self.room_agents, 'recess_yard') def init_agents(room_type, N, partition=False): ''' batch initialize human agents into input room type rooms with equal partition size room_type: a valid string of room type: [None, 'restroom_grade_boys', 'lunch_room', 'classroom_grade', 'restroom_all', 'restroom_grade_girls', 'restroom_KG', 'classroom_KG', 'community_room', 'library', 'restroom_special_education', 'restroom_faculty', 'classroom_special_education', 'health_room', 'faculty_lounge', 'classroom_preschool', 'restroom_preschool'] ''' rooms = find_room_type(self.room_agents, room_type) # if student group should be seperated to different day schedules # assigning schedule_id to equally partitioned rooms # currently only grade 1-5 "grade" students need to be partitioned, partition_size = len(rooms) if partition: partition_size = math.ceil(partition_size / len(self.schedule_ids)) class_size = N // len(rooms) remaining_size = N % len(rooms) for i, classroom in zip(range(len(rooms)), rooms): classroom.generate_seats(class_size, self.seat_dist) classroom.schedule_id = self.schedule_ids[i // partition_size] for idx in range(class_size): pnt = classroom.seats[idx] mask_on = np.random.choice([True, False], p=[mask_prob, 1 - mask_prob]) agent_point = Student(model=self, shape=pnt, unique_id="S" + str(self.__student_id), room=classroom, mask_on=mask_on) self.grid.add_agents(agent_point) self.schedule.add(agent_point) self.__student_id += 1 # spread remaining student into all classrooms if remaining_size > 0: pnt = classroom.seats[class_size] mask_on = np.random.choice([True, False], p=[mask_prob, 1 - mask_prob]) agent_point = Student(model=self, shape=pnt, unique_id="S" + str(self.__student_id), room=classroom, mask_on=mask_on) self.grid.add_agents(agent_point) self.schedule.add(agent_point) self.__student_id += 1 remaining_size -= 1 #add teacher to class pnt = generate_random(classroom.shape) agent_point = Teacher(model=self, shape=pnt, unique_id="T" + str(self.__teacher_id), room=classroom) self.grid.add_agents(agent_point) self.schedule.add(agent_point) self.idle_teachers.append(agent_point) self.__teacher_id += 1 self.__faculty_N -= 1 # initialize all students and teachers in classrooms init_agents("classroom_grade", int(grade_N * attend_rate), partition=True) # keep track of student types #self.grade_students = [a for a in list(self.schedule.agents) if isinstance(a, Student)] init_agents("classroom_KG", int(KG_N * attend_rate)) init_agents("classroom_preschool", int(preschool_N * attend_rate)) #self.pkg_students = [a for a in list(set(self.schedule.agents).difference(self.grade_students)) if isinstance(a, Student)] init_agents("classroom_special_education", int(special_education_N * attend_rate)) # dump remaining teacher to faculty lounge for f_lounge in find_room_type(self.room_agents, "faculty_lounge"): f_lounge.schedule_id = self.schedule_ids[0] for i in range(self.__faculty_N): pnt = generate_random(f_lounge.shape) agent_point = Teacher(model=self, shape=pnt, unique_id="T" + str(self.__teacher_id), room=f_lounge) self.grid.add_agents(agent_point) self.schedule.add(agent_point) self.__teacher_id += 1 #self.people = list(self.schedule.agents) # add rooms to scheduler at last for room in self.room_agents: self.schedule.add(room) self.lunchroom = find_room_type(self.room_agents, 'lunch_room')[0] self.lunchroom.generate_seats_lunch(3, 12)
class School(Model): def __init__(self, map_path, schedule_path, grade_N, KG_N, preschool_N, special_education_N, faculty_N, seat_dist, init_patient=3, attend_rate=1, mask_prob=0.516, inclass_lunch=False, username="******"): # zipcode etc, for access of more realistic population from KG perhaps # model param init self.__mask_prob = mask_prob self.inclass_lunch = inclass_lunch self.seat_dist = math.ceil(seat_dist / (attend_rate**(1 / 2))) self.idle_teachers = [] # teachers to be assigned without a classroom self.init_patient = init_patient # mesa model init self.running = True self.grid = GeoSpace() self.schedule = BaseScheduler(self) #data collect init model_reporters = { "day": "day_count", "cov_positive": "infected_count" } agent_reporters = { "unique_id": "unique_id", "health_status": "health_status", "symptoms": "symptoms", "x": "x", "y": "y", "viral_load": "viral_load" } self.datacollector = datacollection.DataCollector( model_reporters=model_reporters, agent_reporters=agent_reporters) school_gdf = load_map(map_path) # room agent init self.room_agents = school_gdf.apply( lambda x: Classroom(unique_id=x["Id"], model=self, shape=x["geometry"], room_type=x["room_type"]), axis=1).tolist() self.grid.add_agents(self.room_agents) # stats tracking init self.infected_count = 0 self.step_count = 0 self.day_count = 0 self.num_exposed = 0 # student activity init self.schoolday_schedule = pd.read_csv(schedule_path) self.activity = None # id tracking init self.__teacher_id = 0 self.__student_id = 0 self.__faculty_N = faculty_N self.schedule_ids = self.schoolday_schedule.columns self.recess_yards = find_room_type(self.room_agents, 'recess_yard') def init_agents(room_type, N, partition=False): ''' batch initialize human agents into input room type rooms with equal partition size room_type: a valid string of room type: [None, 'restroom_grade_boys', 'lunch_room', 'classroom_grade', 'restroom_all', 'restroom_grade_girls', 'restroom_KG', 'classroom_KG', 'community_room', 'library', 'restroom_special_education', 'restroom_faculty', 'classroom_special_education', 'health_room', 'faculty_lounge', 'classroom_preschool', 'restroom_preschool'] ''' rooms = find_room_type(self.room_agents, room_type) # if student group should be seperated to different day schedules # assigning schedule_id to equally partitioned rooms # currently only grade 1-5 "grade" students need to be partitioned, partition_size = len(rooms) if partition: partition_size = math.ceil(partition_size / len(self.schedule_ids)) class_size = N // len(rooms) remaining_size = N % len(rooms) for i, classroom in zip(range(len(rooms)), rooms): classroom.generate_seats(class_size, self.seat_dist) classroom.schedule_id = self.schedule_ids[i // partition_size] for idx in range(class_size): pnt = classroom.seats[idx] mask_on = np.random.choice([True, False], p=[mask_prob, 1 - mask_prob]) agent_point = Student(model=self, shape=pnt, unique_id="S" + str(self.__student_id), room=classroom, mask_on=mask_on) self.grid.add_agents(agent_point) self.schedule.add(agent_point) self.__student_id += 1 # spread remaining student into all classrooms if remaining_size > 0: pnt = classroom.seats[class_size] mask_on = np.random.choice([True, False], p=[mask_prob, 1 - mask_prob]) agent_point = Student(model=self, shape=pnt, unique_id="S" + str(self.__student_id), room=classroom, mask_on=mask_on) self.grid.add_agents(agent_point) self.schedule.add(agent_point) self.__student_id += 1 remaining_size -= 1 #add teacher to class pnt = generate_random(classroom.shape) agent_point = Teacher(model=self, shape=pnt, unique_id="T" + str(self.__teacher_id), room=classroom) self.grid.add_agents(agent_point) self.schedule.add(agent_point) self.idle_teachers.append(agent_point) self.__teacher_id += 1 self.__faculty_N -= 1 # initialize all students and teachers in classrooms init_agents("classroom_grade", int(grade_N * attend_rate), partition=True) # keep track of student types #self.grade_students = [a for a in list(self.schedule.agents) if isinstance(a, Student)] init_agents("classroom_KG", int(KG_N * attend_rate)) init_agents("classroom_preschool", int(preschool_N * attend_rate)) #self.pkg_students = [a for a in list(set(self.schedule.agents).difference(self.grade_students)) if isinstance(a, Student)] init_agents("classroom_special_education", int(special_education_N * attend_rate)) # dump remaining teacher to faculty lounge for f_lounge in find_room_type(self.room_agents, "faculty_lounge"): f_lounge.schedule_id = self.schedule_ids[0] for i in range(self.__faculty_N): pnt = generate_random(f_lounge.shape) agent_point = Teacher(model=self, shape=pnt, unique_id="T" + str(self.__teacher_id), room=f_lounge) self.grid.add_agents(agent_point) self.schedule.add(agent_point) self.__teacher_id += 1 #self.people = list(self.schedule.agents) # add rooms to scheduler at last for room in self.room_agents: self.schedule.add(room) self.lunchroom = find_room_type(self.room_agents, 'lunch_room')[0] self.lunchroom.generate_seats_lunch(3, 12) def small_step(self): self.schedule.step() self.grid._recreate_rtree() def add_N_patient(self, N): patients = random.sample( [a for a in self.schedule.agents if isinstance(a, Student)], N) for p in patients: p.health_status = "exposed" p.asymptomatic = True p.infective = True def show(self): ''' plot current step visualization deprecated since end of model visualization update ''' # UPDATE 10/16: add deprecation warning message = "this function is no longer used for performance issues, check output_image.py for end of model visualization" warnings.warn(message, DeprecationWarning) school_geometry = gpd.GeoSeries([a.shape for a in self.room_agents]) school_map = gpd.GeoDataFrame( {"viral_load": [min(a.viral_load, 5) for a in self.room_agents]}) school_map.geometry = school_geometry basemap = school_map.plot(column="viral_load", cmap="Reds", alpha=0.5, vmin=0, vmax=5) school_map.boundary.plot(ax=basemap, color='k', linewidth=0.2) list( map(lambda a: a.plot(), [ a for a in self.schedule.agents if issubclass(type(a), Human) ])) hour = 9 + self.step_count * 5 // 60 # assume plot start at 9am minute = self.step_count * 5 % 60 plt.title("Iteration: Day {}, ".format(self.day_count + 1) + "%d:%02d" % (hour, minute), fontsize=30) def __update_day(self): ''' update incubation time, reset viral_load, remove symptomatic agents, etc for end of day ''' for a in self.schedule.agents[:]: if issubclass(type(a), Human): if a.symptoms: # remove agent if symptom onset if isinstance(a, Teacher): # assign a new teacher to position new_teacher = self.idle_teachers.pop() new_teacher.shape = a.shape new_teacher.room = a.room new_teacher.classroom = a.classroom self.schedule.remove(a) self.grid.remove_agent(a) # UPDATE 10/16: infectious made obsolete, end of day update rework elif a.health_status == "exposed": # UPDATE 10/17: update infective delay if agent is not infective by end of day a.infective = True a.symptom_countdown -= 1 # calculate when symptoms begin to show using 0-15 density if a.symptom_countdown <= 0: if a.symptom_countdown == 0: self.infected_count += 1 # update model stat for total infected # negative countdown means this agent is asymptomatic if not a.asymptomatic: # this is a really small chance, however possible # set symtoms to true # next day this agent will be removed from the model a.symptoms = True else: # reset viral_load of room agents a.viral_load = 0 def step(self): ''' simulate a day with school day schedule ''' if not self.schedule.steps: self.add_N_patient(self.init_patient) for i, row in self.schoolday_schedule.iterrows(): self.activity = row self.datacollector.collect(self) self.schedule.step() self.grid._recreate_rtree() self.step_count += 1 self.__update_day() self.grid._recreate_rtree() self.day_count += 1 self.step_count = 0
class RecoveryModel(Model): def __init__(self, locations, N1, scheduleClass, initialization=None, seed=None): if initialization == None: raise Exception("Initialization cannot be none") N = len(locations['features'] ) * N1 #N1 =density of housholds in one building #print(N) self.landuse = locations['features'][0]['landuse'] #print(self.landuse[0]) self.running = True self.num_agents = N self.schedule = scheduleClass(self) self.G = nx.complete_graph(self.num_agents) self.nw = NetworkGrid(self.G) self.grid = GeoSpace(crs='epsg:4326') agent_kwargs = dict(model=self, unique_id='id') self.grid.create_agents_from_GeoJSON(locations, agent=LocationAgent, **agent_kwargs) self.locations = list(self.grid.agents) self.initialize(initialization) self.datacollector = DataCollector( agent_reporters={ "NewShape": agent_loc, "Satisfaction": agent_satisfaction, "LandUse": agent_LU, "H**o": agent_homo, "WorkPlace": agent_workplace }) self.grid.update_bbox() self.grid.create_rtree() def initialize(self, initialization): list_of_random_nodes = random.sample(self.G.nodes(), self.num_agents) for i in range(self.num_agents): agent, self.landuse1 = initialization.next('Household ' + str(i), self) self.nw.place_agent(agent, list_of_random_nodes[i]) self.schedule.add(agent) self.grid.add_agent(agent) def calculate_homophily(self): for i in range(self.G.number_of_nodes()): HH_homphily = 0 total_homophily = 0 c = 1 for agent in self.G.node[i]['agent']: attr_self = [agent.workplace, agent.income, agent.education] agent_location = agent.shape for HH in self.locations: if HH.shape.contains(agent_location): HH_polygon = HH.shape neighbor_nodes = self.nw.get_neighbors(i, include_center=False) for node in neighbor_nodes: for nbr in self.G.node[node]['agent']: attr_neighbor = [nbr.workplace, nbr.income, nbr.education] self.G[i][node]['weight'] = jaccard_similarity( attr_self, attr_neighbor) total_homophily = total_homophily + jaccard_similarity( attr_self, attr_neighbor) neighbor_point = nbr.shape if HH_polygon.contains(neighbor_point): c = c + 1 HH_homphily = HH_homphily + jaccard_similarity( attr_self, attr_neighbor) else: pass agent.h**o = total_homophily agent.shomo = HH_homphily / c def step(self): #print (self.schedule.time) self.datacollector.collect(self) self.schedule.step() self.grid.create_rtree() self.calculate_homophily()
def __init__(self, pop_size, init_infected, exposure_distance, infection_risk=0.2): """ Create a new InfectedModel :param pop_size: Size of population :param init_infected: Probability of a person agent to start as infected :param exposure_distance: Proximity distance between agents to be exposed to each other :param infection_risk: Probability of agent to become infected, if it has been exposed to another infected """ self.schedule = BaseScheduler(self) self.grid = GeoSpace() self.steps = 0 self.counts = None self.reset_counts() # SIR model parameters self.pop_size = pop_size self.counts["susceptible"] = pop_size self.exposure_distance = exposure_distance self.infection_risk = infection_risk self.running = True self.datacollector = DataCollector({ "infected": get_infected_count, "susceptible": get_susceptible_count, "recovered": get_recovered_count, "dead": get_dead_count, }) # Set up the Neighbourhood patches for every region in file (add to schedule later) AC = AgentCreator(NeighbourhoodAgent, {"model": self}) neighbourhood_agents = AC.from_file(self.geojson_regions, unique_id=self.unique_id) self.grid.add_agents(neighbourhood_agents) # Generate PersonAgent population ac_population = AgentCreator(PersonAgent, { "model": self, "init_infected": init_infected }) # Generate random location, add agent to grid and scheduler for i in range(pop_size): this_neighbourhood = self.random.randint( 0, len(neighbourhood_agents) - 1) # Region where agent starts center_x, center_y = neighbourhood_agents[ this_neighbourhood].shape.centroid.coords.xy this_bounds = neighbourhood_agents[this_neighbourhood].shape.bounds spread_x = int( this_bounds[2] - this_bounds[0]) # Heuristic for agent spread in region spread_y = int(this_bounds[3] - this_bounds[1]) this_x = center_x[0] + self.random.randint(0, spread_x) - spread_x / 2 this_y = center_y[0] + self.random.randint(0, spread_y) - spread_y / 2 this_person = ac_population.create_agent(Point(this_x, this_y), "P" + str(i)) self.grid.add_agents(this_person) self.schedule.add(this_person) # Add the neighbourhood agents to schedule AFTER person agents, # to allow them to update their color by using BaseScheduler for agent in neighbourhood_agents: self.schedule.add(agent) self.datacollector.collect(self)
structval_4 = rb_4.ReadRaster(px_4, py_4, 1, 1, buf_type=gdal.GDT_Float32) intval_4 = struct.unpack('f', structval_4) gw_temp.append(round(intval_1[0], 2)) gw_power.append(round(intval_2[0], 2)) avg_air_temp.append(round(intval_3[0], 2)) solar_p.append(round(intval_4[0], 2)) # store values in DataFrame df_points['gw_temp'] = gw_temp df_points['gw_power'] = gw_power df_points['air_temp'] = avg_air_temp df_points['solar_p'] = solar_p # read agents as geoAgents grid = GeoSpace() AC = AgentCreator(HouseholdAgent, {"model": None}) households = AC.from_GeoDataFrame(df_points) # pre allocation of result vectors df_points['gas_grid'] = [1] * len(households) neighbors = [None] * len(households) num_neighbors = [0] * len(households) # add agents from geo file to the grid grid.add_agents(households) for household in grid.agents: # get neighbors neighbor_list = [ x.unique_id for x in grid.get_neighbors_within_distance(
def __init__(self, cit_pd, stakeholder_pd, regulator_pd, geojson_list, meta_data, neighbor_type=0, efficiency_parameter=1.5, log_level=0): self.log_level = log_level # * Default values # List of citizen self.cit_list: List[CitAgent] = [] self.cbo_list = [] # List of cits' CBOs # List of those who can negotiate with stakeholder self.sh_negotiator_list = [] # List of CBOs created after negotiating with stakeholder self.sh_in_coalition_list = [] # Can includes cits or stakeholder # Strictly regulator self.regulator_negotiator_list = [] self.regulator_in_coalition_list: List[RegulatorAgent] = [] # For performance issue # we use dict for fast lookup and modification self.agent_dict: Dict[str, All_Agent_Type] = {} # List of stakeholder and regulator from csv file self.sh_list: List[StakeholderAgent] = [] self.regulator_list: List[RegulatorAgent] = [] # Big-NGO and Utility-info self.need: float = 0 self.procedure: float = 0 # Otherb self.is_regulator_anti: bool = False # * Store all the dataframe for later use self.cit_pd = cit_pd self.stakeholder_pd = stakeholder_pd self.regulator_pd = regulator_pd self.print_log(2, "Initializing model") # * Initialize mesa self.grid = GeoSpace(crs={"init": "epsg:4326"}) self.schedule = BaseScheduler(self) self.talk_span: float = meta_data['talk_span'] self.total_cit: int = meta_data['actual_num_cit'] self.disruption: float = meta_data['disruption'] self.need: float = meta_data['need'] self.NGO_message: float = meta_data['NGO_message'] self.procedure: float = meta_data['procedure'] self.sponsor_message: float = meta_data['sponsor_message'] self.neighbor_type: int = neighbor_type self.efficiency_parameter: float = efficiency_parameter # * Initialize citizens self.print_log(2, "Initializing citizens") self.setup_cit(geojson_list) # * Initialize data collectors self.print_log(2, "Initializing data collectors") # Set up data collector self.datacollector = DataCollector(model_reporters={ "Total preference": ModelCalculator.compute_total("pref"), "Total power": ModelCalculator.compute_total("power"), }, agent_reporters={ "Preference": "pref", "Power": "power", }) self.sh_collector: CustomAgentDataCollector = CustomAgentDataCollector( model_reporters={ "Total sh preference": ModelCalculator.compute_total("sh_pref"), }, agent_reporters={ "Stakeholder preference": "sh_pref", }, agent_list=self.sh_list) self.regulator_collector: CustomAgentDataCollector = CustomAgentDataCollector( model_reporters={ "Total regulator preference": ModelCalculator.compute_total("regulator_pref"), }, agent_reporters={ "Regulator preference": "regulator_pref", }, agent_list=self.regulator_list)
def __init__(self, monitored_statistic, show_schools, show_restaurants): """ Create a new InfectedModel """ self.schedule = BaseScheduler(self) self.grid = GeoSpace() self.steps = 0 self.counts = None self.reset_counts() self.monitored_statistic = 'infected-per-home-series' self.show_schools = show_schools self.show_restaurants = show_restaurants self.maximum = {self.monitored_statistic: 0} self.minimum = {self.monitored_statistic: sys.maxsize} with open(LOG_FILE) as json_file: self.simulation_data = json.load(json_file) #for key in self.simulation_data[self.monitored_statistic]: # for v in self.simulation_data[self.monitored_statistic][key]: # if v > self.maximum[self.monitored_statistic]: self.maximum[self.monitored_statistic] = v # if v < self.minimum[self.monitored_statistic]: self.minimum[self.monitored_statistic] = v self.minimum['infected-per-home-series'] = 0 self.maximum['infected-per-home-series'] = 500 self.running = True self.datacollector = DataCollector({ "infected": get_infected_count, "susceptible": get_susceptible_count, "recovered": get_recovered_count, "dead": get_dead_count, }) # Neighboorhoods AC = AgentCreator(NeighbourhoodAgent, {"model": self}) neighbourhood_agents = AC.from_file(geojson_neighborhoods, unique_id=self.unique_id) for agent in neighbourhood_agents: for neighborhood in NEIGHBORHOODS['features']: if agent.unique_id == neighborhood['properties']['NAME']: agent2feature[agent.unique_id] = neighborhood break self.grid.add_agents(neighbourhood_agents) # Schools AC = AgentCreator(SchoolAgent, {"model": self}) school_agents = AC.from_file(geojson_schools, unique_id=self.unique_id) for agent in school_agents: for school in SCHOOLS['features']: if agent.unique_id == school['properties']['NAME']: agent2feature[agent.unique_id] = school break self.grid.add_agents(school_agents) # Restaurants AC = AgentCreator(RestaurantAgent, {"model": self}) restaurant_agents = AC.from_file(geojson_restaurants, unique_id=self.unique_id) for agent in restaurant_agents: for restaurant in RESTAURANTS['features']: if agent.unique_id == restaurant['properties']['NAME']: agent2feature[agent.unique_id] = restaurant break self.grid.add_agents(restaurant_agents) for agent in neighbourhood_agents + school_agents: self.schedule.add(agent) self.datacollector.collect(self)
class School(Model): schedule_types = { "Sequential": BaseScheduler, "Random": RandomActivation, "Simultaneous": SimultaneousActivation } def __init__(self, map_path, schedule_path, grade_N, KG_N, preschool_N, special_education_N, faculty_N, seat_dist, init_patient=3, attend_rate=1, mask_prob=0.516, inclass_lunch=False, student_vaccine_prob=0, student_testing_freq=14, teacher_vaccine_prob=1, teacher_testing_freq=7, teacher_mask='N95', schedule_type="Simultaneous"): # zipcode etc, for access of more realistic population from KG perhaps # model param init self.__mask_prob = mask_prob self.inclass_lunch = inclass_lunch self.seat_dist = math.ceil(seat_dist / (attend_rate**(1 / 2))) self.idle_teachers = [] # teachers to be assigned without a classroom self.init_patient = init_patient # testing param init self.teacher_testing_freq = teacher_testing_freq self.student_testing_freq = student_testing_freq # mesa model init self.running = True self.grid = GeoSpace() self.schedule_type = schedule_type self.schedule = self.schedule_types[self.schedule_type](self) #data collect init model_reporters = { "day": "day_count", "cov_positive": "infected_count" } agent_reporters = { "unique_id": "unique_id", "health_status": "health_status", "symptoms": "symptoms", "x": "x", "y": "y", "viral_load": "viral_load" } self.datacollector = datacollection.DataCollector( model_reporters=model_reporters, agent_reporters=agent_reporters) school_gdf = gpd.read_file(map_path) # minx miny maxx maxy # use minx maxy # gdf.dessolve # minx miny maxx maxy = geometery.bounds # for loop: # bus = bus(shape(minx,maxy)) # minx = minx - width # maxy = maxy + length # room agent init self.room_agents = school_gdf.apply( lambda x: room_agent.Classroom(unique_id=x["Id"], model=self, shape=x["geometry"], room_type=x["room_type"]), axis=1).tolist() self.grid.add_agents(self.room_agents) # stats tracking init self.infected_count = 0 self.step_count = 0 self.day_count = 1 self.num_exposed = 0 # student activity init self.schoolday_schedule = pd.read_csv(schedule_path) self.activity = None # id tracking init self.__teacher_id = 0 self.__student_id = 0 self.__cohort_id = 0 self.__faculty_N = faculty_N self.schedule_ids = self.schoolday_schedule.columns # geo-object tracking init self.recess_yards = util.find_room_type(self.room_agents, 'recess_yard') self.cohorts = [] # UPDATE Christmas cohort generation def generate_cohorts(students, N): ''' generate cohorts with within/out-of classroom probability, cohort size probablity example: students have 80% chance to have a friend in same room, 20% chance to have a friend in different room and 50% to have a cohort size of 5, 20% size 2, 15% size 4, 10% size 3, 5% size 1 students: a 2d list containing list of students in each room students[k] is a list of student agents (in same classroom room) ''' size_prob = eval(cohort_config['size_prob']) same_room_prob = eval(cohort_config['same_room_prob']) radius = eval(cohort_config['radius']) size_val_list = list(size_prob.keys()) size_prob_list = list(size_prob.values()) same_room_val_list = list(same_room_prob.keys()) same_room_prob_list = list(same_room_prob.values()) # start at room 0 cur_room = 0 while N > 0: cur_size = np.random.choice(size_val_list, p=size_prob_list) if N <= max(size_val_list): cur_size = N # get same-room cohort size cur_same = sum( np.random.choice(same_room_val_list, size=cur_size, p=same_room_prob_list)) # add students from current room to current cohort cur_same = min(cur_same, len(students[cur_room])) cohort = students[cur_room][:cur_same] students[cur_room] = students[cur_room][cur_same:] room_idx = list(range(len(students))) other_room = room_idx[:] other_room.remove(cur_room) # add students from other rooms to cohort if not len(other_room): rand_room = [cur_room] * (cur_size - cur_same) else: rand_room = np.random.choice(other_room, size=(cur_size - cur_same)) for r in rand_room: # update and remove r if r is an empty room while True: try: cohort.append(students[r][0]) students[r] = students[r][1:] break except: if r in other_room: other_room.remove(r) if not len(other_room): r = cur_room else: r = np.random.choice(other_room) # TODO: recess yard is current hard coded recess_yard = self.recess_yards[0] if cohort[0].grade != 'grade': recess_yard = self.recess_yards[1] # make cohort agent with dummy shape cur_cohort = cohort_agent.Cohort( "Cohort" + str(self.__cohort_id), self, Point(0, 0), cohort, recess_yard, cur_size * radius) self.grid.add_agents(cur_cohort) self.schedule.add(cur_cohort) self.cohorts.append(cur_cohort) self.__cohort_id += 1 # remove empty rooms students = [room for room in students if len(room) > 0] # rolling update to minimize student pop edge cases # fail safe break if not len(students): break cur_room = (cur_room + 1) % len(students) # update student population N -= cur_size def init_agents(room_type, N, partition=False): ''' batch initialize human agents into input room type rooms with equal partition size room_type: a valid string of room type: [None, 'restroom_grade_boys', 'lunch_room', 'classroom_grade', 'restroom_all', 'restroom_grade_girls', 'restroom_KG', 'classroom_KG', 'community_room', 'library', 'restroom_special_education', 'restroom_faculty', 'classroom_special_education', 'health_room', 'faculty_lounge', 'classroom_preschool', 'restroom_preschool'] ''' rooms = util.find_room_type(self.room_agents, room_type) # if student group should be seperated to different day schedules # assigning schedule_id to equally partitioned rooms # currently only grade 1-5 "grade" students need to be partitioned, partition_size = len(rooms) if partition: partition_size = math.ceil(partition_size / len(self.schedule_ids)) class_size = N // len(rooms) remaining_size = N % len(rooms) #track all students of same grade type all_students = [] for i, classroom in zip(range(len(rooms)), rooms): # spread remaining student into all classrooms c_size = class_size if remaining_size > 0: remaining_size -= 1 c_size += 1 #each classroom has its own possibility to have circular desks instead of normal grid seating #TODO: strongly believe this is subject to change prob_circular = eval(population_config['circular_desk_prob']) if np.random.choice([True, False], p=[prob_circular, 1 - prob_circular]): classroom.generate_seats(c_size, self.seat_dist, style='circular') else: classroom.generate_seats(c_size, self.seat_dist) classroom.schedule_id = self.schedule_ids[i // partition_size] #track students within the same room students = [] for idx in range(c_size): pnt = classroom.seats[idx] mask_on = np.random.choice([True, False], p=[mask_prob, 1 - mask_prob]) agent_point = human_agent.Student(model=self, shape=pnt, unique_id="S" + str(self.__student_id), room=classroom, mask_on=mask_on) # vaccinate students accordingly agent_point.vaccinated = np.random.choice( [True, False], p=[student_vaccine_prob, 1 - student_vaccine_prob]) if classroom.seating_pattern == 'circular': desks = gpd.GeoSeries(classroom.desks) agent_point.desk = desks[desks.distance( agent_point.shape).sort_values().index[0]] self.grid.add_agents(agent_point) self.schedule.add(agent_point) self.__student_id += 1 # add student to room temp list students.append(agent_point) #add teacher to class pnt = util.generate_random(classroom.shape) agent_point = human_agent.Teacher(model=self, shape=pnt, unique_id="T" + str(self.__teacher_id), room=classroom) # teacher mask/vaccination protocol agent_point.vaccinated = np.random.choice( [True, False], p=[teacher_vaccine_prob, 1 - teacher_vaccine_prob]) agent_point.mask_type = teacher_mask agent_point.mask_passage_prob = trans_rate.return_mask_passage_prob( teacher_mask) self.grid.add_agents(agent_point) self.schedule.add(agent_point) self.__teacher_id += 1 self.__faculty_N -= 1 # add room students list to all students # shuffle students for efficiency improvement np.random.shuffle(students) all_students.append(students) #UPDATE Christmas #generate cohort with temp student list generate_cohorts(all_students, N) # initialize all students and teachers in classrooms init_agents("classroom_grade", int(grade_N * attend_rate), partition=True) # keep track of student types #self.grade_students = [a for a in list(self.schedule.agents) if isinstance(a, Student)] init_agents("classroom_KG", int(KG_N * attend_rate)) init_agents("classroom_preschool", int(preschool_N * attend_rate)) #self.pkg_students = [a for a in list(set(self.schedule.agents).difference(self.grade_students)) if isinstance(a, Student)] init_agents("classroom_special_education", int(special_education_N * attend_rate)) # dump remaining teacher to faculty lounge for f_lounge in util.find_room_type(self.room_agents, "faculty_lounge"): f_lounge.schedule_id = self.schedule_ids[0] for i in range(self.__faculty_N): pnt = util.generate_random(f_lounge.shape) agent_point = human_agent.Teacher(model=self, shape=pnt, unique_id="T" + str(self.__teacher_id), room=f_lounge) # teacher mask/vaccination protocol agent_point.vaccinated = np.random.choice( [True, False], p=[teacher_vaccine_prob, 1 - teacher_vaccine_prob]) agent_point.mask_type = teacher_mask agent_point.mask_passage_prob = trans_rate.return_mask_passage_prob( teacher_mask) self.grid.add_agents(agent_point) self.schedule.add(agent_point) #teacher from faculty lounge can be used later if on duty teachers test positive self.idle_teachers.append(agent_point) self.__teacher_id += 1 # add rooms to scheduler at last for room in self.room_agents: self.schedule.add(room) self.lunchroom = util.find_room_type(self.room_agents, 'lunch_room')[0] self.lunchroom.generate_seats_lunch(1, 4) def small_step(self): self.schedule.step() self.grid._recreate_rtree() def add_N_patient(self, N): patients = random.sample([ a for a in self.schedule.agents if isinstance(a, human_agent.Student) ], N) for p in patients: p.health_status = "exposed" p.asymptomatic = True p.infective = True def show(self): ''' plot current step visualization deprecated since end of model visualization update ''' # UPDATE 10/16: add deprecation warning message = "this function is no longer used for performance issues, check output_image.py for end of model visualization" warnings.warn(message, DeprecationWarning) school_geometry = gpd.GeoSeries([a.shape for a in self.room_agents]) school_map = gpd.GeoDataFrame( {"viral_load": [min(a.viral_load, 5) for a in self.room_agents]}) school_map.geometry = school_geometry basemap = school_map.plot(column="viral_load", cmap="Reds", alpha=0.5, vmin=0, vmax=5) school_map.boundary.plot(ax=basemap, color='k', linewidth=0.2) list( map(lambda a: a.plot(), [ a for a in self.schedule.agents if issubclass(type(a), human_agent.Human) ])) hour = 9 + self.step_count * 5 // 60 # assume plot start at 9am minute = self.step_count * 5 % 60 plt.title("Iteration: Day {}, ".format(self.day_count) + "%d:%02d" % (hour, minute), fontsize=30) def __update_day(self): ''' update incubation time, reset viral_load, remove symptomatic agents, aerosol transmission etc for end of day ''' for a in self.schedule.agents[:]: # update human agent disease stats if issubclass(type(a), human_agent.Human): if a.symptoms: # remove agent if symptom onset if isinstance(a, human_agent.Teacher) and len( self.idle_teachers) > 0: # assign a new teacher to position new_teacher = self.idle_teachers.pop() new_teacher.shape = a.shape new_teacher.room = a.room new_teacher.classroom = a.classroom self.schedule.remove(a) self.grid.remove_agent(a) # UPDATE 10/16: infectious made obsolete, end of day update rework elif a.health_status == "exposed": # UPDATE 2/28: merge testing implementation # test student and teacher accordingly # Q: why testing is here under exposed case?: # testing only matters if infect the result is a hit # therefore the agnent gets removed only if two conditions are met # 1.testing is arranged; 2. testing result the agent is indeed exposed if isinstance(a, human_agent.Teacher) and ( self.day_count % self.teacher_testing_freq == 0): # if hit teacher, try to assign a new teacher to position if len(self.idle_teachers) > 0: new_teacher = self.idle_teachers.pop() new_teacher.shape = a.shape new_teacher.room = a.room new_teacher.classroom = a.classroom #remove teacher if testing conditions are met self.schedule.remove(a) self.grid.remove_agent(a) elif isinstance(a, human_agent.Student) and ( self.day_count % self.student_testing_freq == 0): #remove student if testing conditions are met self.schedule.remove(a) self.grid.remove_agent(a) # UPDATE 10/17: update infective delay if agent is not infective by end of day a.infective = True a.symptom_countdown -= 1 # calculate when symptoms begin to show using 0-15 density if a.symptom_countdown <= 0: if a.symptom_countdown == 0: self.infected_count += 1 # update model stat for total infected # negative countdown means this agent is asymptomatic if not a.asymptomatic: # this is a really small chance, however possible # set symtoms to true # next day this agent will be removed from the model a.symptoms = True # update room agent aerosal stats elif issubclass(type(a), room_agent.Classroom): room = a mean_aerosol_transmissions = sum( room.aerosol_transmission_rate) if np.isnan(mean_aerosol_transmissions): mean_aerosol_transmissions = 0 occupants = [ a for a in list(self.grid.get_intersecting_agents(room)) if issubclass(type(a), human_agent.Human) ] healthy_occupants = [ a for a in occupants if a.health_status == 'healthy' ] # failsafe for rare case where this can exceed one mean_aerosol_transmissions = min(mean_aerosol_transmissions, 1) # treating aerosal transmissions as a probability for each healthy occupant in this room to get sick for healthy_occupant in healthy_occupants: if np.random.choice([True, False], p=[ mean_aerosol_transmissions, 1 - mean_aerosol_transmissions ]): if not healthy_occupant.vaccinated: healthy_occupant.health_status = 'exposed' def step(self): ''' simulate a day with school day schedule ''' if not self.schedule.steps: self.add_N_patient(self.init_patient) for i, row in self.schoolday_schedule.iterrows(): self.activity = row self.datacollector.collect(self) self.schedule.step() self.grid._recreate_rtree() self.step_count += 1 self.__update_day() self.grid._recreate_rtree() self.day_count += 1 self.step_count = 0
def __init__(self, map_path, schedule_path, grade_N, KG_N, preschool_N, special_education_N, faculty_N, seat_dist, init_patient=3, attend_rate=1, mask_prob=0.516, inclass_lunch=False, student_vaccine_prob=0, student_testing_freq=14, teacher_vaccine_prob=1, teacher_testing_freq=7, teacher_mask='N95', schedule_type="Simultaneous"): # zipcode etc, for access of more realistic population from KG perhaps # model param init self.__mask_prob = mask_prob self.inclass_lunch = inclass_lunch self.seat_dist = math.ceil(seat_dist / (attend_rate**(1 / 2))) self.idle_teachers = [] # teachers to be assigned without a classroom self.init_patient = init_patient # testing param init self.teacher_testing_freq = teacher_testing_freq self.student_testing_freq = student_testing_freq # mesa model init self.running = True self.grid = GeoSpace() self.schedule_type = schedule_type self.schedule = self.schedule_types[self.schedule_type](self) #data collect init model_reporters = { "day": "day_count", "cov_positive": "infected_count" } agent_reporters = { "unique_id": "unique_id", "health_status": "health_status", "symptoms": "symptoms", "x": "x", "y": "y", "viral_load": "viral_load" } self.datacollector = datacollection.DataCollector( model_reporters=model_reporters, agent_reporters=agent_reporters) school_gdf = gpd.read_file(map_path) # minx miny maxx maxy # use minx maxy # gdf.dessolve # minx miny maxx maxy = geometery.bounds # for loop: # bus = bus(shape(minx,maxy)) # minx = minx - width # maxy = maxy + length # room agent init self.room_agents = school_gdf.apply( lambda x: room_agent.Classroom(unique_id=x["Id"], model=self, shape=x["geometry"], room_type=x["room_type"]), axis=1).tolist() self.grid.add_agents(self.room_agents) # stats tracking init self.infected_count = 0 self.step_count = 0 self.day_count = 1 self.num_exposed = 0 # student activity init self.schoolday_schedule = pd.read_csv(schedule_path) self.activity = None # id tracking init self.__teacher_id = 0 self.__student_id = 0 self.__cohort_id = 0 self.__faculty_N = faculty_N self.schedule_ids = self.schoolday_schedule.columns # geo-object tracking init self.recess_yards = util.find_room_type(self.room_agents, 'recess_yard') self.cohorts = [] # UPDATE Christmas cohort generation def generate_cohorts(students, N): ''' generate cohorts with within/out-of classroom probability, cohort size probablity example: students have 80% chance to have a friend in same room, 20% chance to have a friend in different room and 50% to have a cohort size of 5, 20% size 2, 15% size 4, 10% size 3, 5% size 1 students: a 2d list containing list of students in each room students[k] is a list of student agents (in same classroom room) ''' size_prob = eval(cohort_config['size_prob']) same_room_prob = eval(cohort_config['same_room_prob']) radius = eval(cohort_config['radius']) size_val_list = list(size_prob.keys()) size_prob_list = list(size_prob.values()) same_room_val_list = list(same_room_prob.keys()) same_room_prob_list = list(same_room_prob.values()) # start at room 0 cur_room = 0 while N > 0: cur_size = np.random.choice(size_val_list, p=size_prob_list) if N <= max(size_val_list): cur_size = N # get same-room cohort size cur_same = sum( np.random.choice(same_room_val_list, size=cur_size, p=same_room_prob_list)) # add students from current room to current cohort cur_same = min(cur_same, len(students[cur_room])) cohort = students[cur_room][:cur_same] students[cur_room] = students[cur_room][cur_same:] room_idx = list(range(len(students))) other_room = room_idx[:] other_room.remove(cur_room) # add students from other rooms to cohort if not len(other_room): rand_room = [cur_room] * (cur_size - cur_same) else: rand_room = np.random.choice(other_room, size=(cur_size - cur_same)) for r in rand_room: # update and remove r if r is an empty room while True: try: cohort.append(students[r][0]) students[r] = students[r][1:] break except: if r in other_room: other_room.remove(r) if not len(other_room): r = cur_room else: r = np.random.choice(other_room) # TODO: recess yard is current hard coded recess_yard = self.recess_yards[0] if cohort[0].grade != 'grade': recess_yard = self.recess_yards[1] # make cohort agent with dummy shape cur_cohort = cohort_agent.Cohort( "Cohort" + str(self.__cohort_id), self, Point(0, 0), cohort, recess_yard, cur_size * radius) self.grid.add_agents(cur_cohort) self.schedule.add(cur_cohort) self.cohorts.append(cur_cohort) self.__cohort_id += 1 # remove empty rooms students = [room for room in students if len(room) > 0] # rolling update to minimize student pop edge cases # fail safe break if not len(students): break cur_room = (cur_room + 1) % len(students) # update student population N -= cur_size def init_agents(room_type, N, partition=False): ''' batch initialize human agents into input room type rooms with equal partition size room_type: a valid string of room type: [None, 'restroom_grade_boys', 'lunch_room', 'classroom_grade', 'restroom_all', 'restroom_grade_girls', 'restroom_KG', 'classroom_KG', 'community_room', 'library', 'restroom_special_education', 'restroom_faculty', 'classroom_special_education', 'health_room', 'faculty_lounge', 'classroom_preschool', 'restroom_preschool'] ''' rooms = util.find_room_type(self.room_agents, room_type) # if student group should be seperated to different day schedules # assigning schedule_id to equally partitioned rooms # currently only grade 1-5 "grade" students need to be partitioned, partition_size = len(rooms) if partition: partition_size = math.ceil(partition_size / len(self.schedule_ids)) class_size = N // len(rooms) remaining_size = N % len(rooms) #track all students of same grade type all_students = [] for i, classroom in zip(range(len(rooms)), rooms): # spread remaining student into all classrooms c_size = class_size if remaining_size > 0: remaining_size -= 1 c_size += 1 #each classroom has its own possibility to have circular desks instead of normal grid seating #TODO: strongly believe this is subject to change prob_circular = eval(population_config['circular_desk_prob']) if np.random.choice([True, False], p=[prob_circular, 1 - prob_circular]): classroom.generate_seats(c_size, self.seat_dist, style='circular') else: classroom.generate_seats(c_size, self.seat_dist) classroom.schedule_id = self.schedule_ids[i // partition_size] #track students within the same room students = [] for idx in range(c_size): pnt = classroom.seats[idx] mask_on = np.random.choice([True, False], p=[mask_prob, 1 - mask_prob]) agent_point = human_agent.Student(model=self, shape=pnt, unique_id="S" + str(self.__student_id), room=classroom, mask_on=mask_on) # vaccinate students accordingly agent_point.vaccinated = np.random.choice( [True, False], p=[student_vaccine_prob, 1 - student_vaccine_prob]) if classroom.seating_pattern == 'circular': desks = gpd.GeoSeries(classroom.desks) agent_point.desk = desks[desks.distance( agent_point.shape).sort_values().index[0]] self.grid.add_agents(agent_point) self.schedule.add(agent_point) self.__student_id += 1 # add student to room temp list students.append(agent_point) #add teacher to class pnt = util.generate_random(classroom.shape) agent_point = human_agent.Teacher(model=self, shape=pnt, unique_id="T" + str(self.__teacher_id), room=classroom) # teacher mask/vaccination protocol agent_point.vaccinated = np.random.choice( [True, False], p=[teacher_vaccine_prob, 1 - teacher_vaccine_prob]) agent_point.mask_type = teacher_mask agent_point.mask_passage_prob = trans_rate.return_mask_passage_prob( teacher_mask) self.grid.add_agents(agent_point) self.schedule.add(agent_point) self.__teacher_id += 1 self.__faculty_N -= 1 # add room students list to all students # shuffle students for efficiency improvement np.random.shuffle(students) all_students.append(students) #UPDATE Christmas #generate cohort with temp student list generate_cohorts(all_students, N) # initialize all students and teachers in classrooms init_agents("classroom_grade", int(grade_N * attend_rate), partition=True) # keep track of student types #self.grade_students = [a for a in list(self.schedule.agents) if isinstance(a, Student)] init_agents("classroom_KG", int(KG_N * attend_rate)) init_agents("classroom_preschool", int(preschool_N * attend_rate)) #self.pkg_students = [a for a in list(set(self.schedule.agents).difference(self.grade_students)) if isinstance(a, Student)] init_agents("classroom_special_education", int(special_education_N * attend_rate)) # dump remaining teacher to faculty lounge for f_lounge in util.find_room_type(self.room_agents, "faculty_lounge"): f_lounge.schedule_id = self.schedule_ids[0] for i in range(self.__faculty_N): pnt = util.generate_random(f_lounge.shape) agent_point = human_agent.Teacher(model=self, shape=pnt, unique_id="T" + str(self.__teacher_id), room=f_lounge) # teacher mask/vaccination protocol agent_point.vaccinated = np.random.choice( [True, False], p=[teacher_vaccine_prob, 1 - teacher_vaccine_prob]) agent_point.mask_type = teacher_mask agent_point.mask_passage_prob = trans_rate.return_mask_passage_prob( teacher_mask) self.grid.add_agents(agent_point) self.schedule.add(agent_point) #teacher from faculty lounge can be used later if on duty teachers test positive self.idle_teachers.append(agent_point) self.__teacher_id += 1 # add rooms to scheduler at last for room in self.room_agents: self.schedule.add(room) self.lunchroom = util.find_room_type(self.room_agents, 'lunch_room')[0] self.lunchroom.generate_seats_lunch(1, 4)
class NaiveModel(Model): ''' this class represents the environment that the agents are present in, and the steps are the steps in the agent based model. There are a few parameters that are included in this class: - agent_class: this is basically what the agent is, which in our case is the busAgent that we created earlier - dim_bus: these are the dimensions of the bus. the format is a list: [num_left_columns, num_middle_columns, num right_columns, num_rows]. There will not be passengers in the middle column; this is simply to provide some area between passengers (which is realistic amongst the bus). - distance_seats: this sets the distance between seats in feet. This will affect how close the passangers are to each other and thus affect the rate of infection - num_infected: this is the number of people initially infected ''' def __init__(self, agent_class, num_col_left, num_col_mid, num_col_right, num_row, dist_bw_seats, num_infected, breath_prob, cough_prob, sneeze_prob, breath_dist, cough_dist, sneeze_dist, prob_infected): # mesa required attributes self.running = True self.grid = GeoSpace() self.schedule = BaseScheduler( self ) # scheduler dictates model level agent behavior, aka. step function # variables used for later functions that need descriptions of the model dim_bus = [num_col_left, num_col_mid, num_col_right, num_row] self.max_columns = (dim_bus[0] + dim_bus[1] + dim_bus[2]) * dist_bw_seats self.max_rows = dim_bus[3] * dist_bw_seats self.seat_dist = dist_bw_seats i = 1 for x in range(0, dim_bus[0] * dist_bw_seats, dist_bw_seats): for y in range(0, dim_bus[3] * dist_bw_seats, dist_bw_seats): pnt = Point(x, y) i += 1 a = agent_class(model=self, shape=pnt, unique_id="na" + str(i), breath_prob=breath_prob, cough_prob=cough_prob, sneeze_prob=sneeze_prob, breath_dist=breath_dist, cough_dist=cough_dist, sneeze_dist=sneeze_dist, prob_infected=prob_infected) self.grid.add_agents(a) self.schedule.add(a) for x in range((dim_bus[0] + dim_bus[1]) * dist_bw_seats, (dim_bus[0] + dim_bus[1] + dim_bus[2]) * dist_bw_seats, dist_bw_seats): for y in range(0, dim_bus[3] * dist_bw_seats, dist_bw_seats): pnt = Point(x, y) i += 1 a = agent_class(model=self, shape=pnt, unique_id="na" + str(i), breath_prob=breath_prob, cough_prob=cough_prob, sneeze_prob=sneeze_prob, breath_dist=breath_dist, cough_dist=cough_dist, sneeze_dist=sneeze_dist, prob_infected=prob_infected) self.grid.add_agents(a) self.schedule.add(a) infected_agents = random.sample(self.grid.agents, num_infected) for i in infected_agents: i.infected = True def step(self): ''' step function of the model that would essentially call the step function of all agents ''' self.schedule.step() self.grid._recreate_rtree( ) # this is some history remaining issue with the mesa-geo package
def __init__( self, student_class, params ): #student_num, sick_num, bus_cols, bus_rows, highrisk_radius, highrisk, lowrisk_radius, lowrisk, masks): # mesa required attributes self.running = True # determines if model should keep on running # should be specified to false when given conditions are met self.grid = GeoSpace( ) # To learn more about other type of space grid, check mesa documentation self.schedule = SimultaneousActivation( self ) # scheduler dictates model level agent behavior, aka. step function # Here we are using a BaseScheduler which computes step of the agents by order # To learn more about other type of scheduler, check mesa documentation student_num = params['student_num'] sick_num = params['sick_num'] bus_cols = params['bus_cols'] bus_rows = params['bus_rows'] breathe_rate = params["breathe_rate"], windows_open = params["windows_open"], seating_array = params["seating_array"], highrisk_radius = params['highrisk_radius'] highrisk = params['highrisk'] lowrisk_radius = params['lowrisk_radius'] lowrisk = params['lowrisk'] masks = params['masks'] bus_stop_student_count = params['bus_stop_student_count'] bus_stop_minutes_count = params['bus_stop_minutes_count'] sick = 0 locs = [] # initializing the model by making the students and putting them into their seats stop_counter = 0 for i in range(student_num): bus_stop = bus_stop_minutes_count[bus_stop_student_count.index( min(filter(lambda x: x > stop_counter, bus_stop_student_count)))] stop_counter += 1 # finding an empty seat for the next student new = False while (new == False): loc = (np.random.randint(bus_cols), np.random.randint(bus_rows)) if loc not in locs: new = True locs.append(loc) pnt = Point(loc) # adding sick and healthy students if sick < sick_num: sick += 1 a = Student(model=self, shape=pnt, unique_id="Passenger #" + str(i), sick=True, mask=False, params=params, spreads=True, bus_stop=bus_stop, breathe_rate=breathe_rate) else: a = Student(model=self, shape=pnt, unique_id="Passenger #" + str(i), sick=False, mask=False, params=params, spreads=False, bus_stop=bus_stop, breathe_rate=breathe_rate) self.grid.add_agents(a) self.schedule.add(a)
class InfectedModel(Model): """Model class for a simplistic infection model.""" # Geographical parameters for desired map MAP_COORDS = [43.741667, -79.373333] # Toronto geojson_regions = "TorontoNeighbourhoods.geojson" unique_id = "HOODNUM" def __init__(self, pop_size, init_infected, exposure_distance, infection_risk=0.2): """ Create a new InfectedModel :param pop_size: Size of population :param init_infected: Probability of a person agent to start as infected :param exposure_distance: Proximity distance between agents to be exposed to each other :param infection_risk: Probability of agent to become infected, if it has been exposed to another infected """ self.schedule = BaseScheduler(self) self.grid = GeoSpace() self.steps = 0 self.counts = None self.reset_counts() # SIR model parameters self.pop_size = pop_size self.counts["susceptible"] = pop_size self.exposure_distance = exposure_distance self.infection_risk = infection_risk self.running = True self.datacollector = DataCollector({ "infected": get_infected_count, "susceptible": get_susceptible_count, "recovered": get_recovered_count, "dead": get_dead_count, }) # Set up the Neighbourhood patches for every region in file (add to schedule later) AC = AgentCreator(NeighbourhoodAgent, {"model": self}) neighbourhood_agents = AC.from_file(self.geojson_regions, unique_id=self.unique_id) self.grid.add_agents(neighbourhood_agents) # Generate PersonAgent population ac_population = AgentCreator(PersonAgent, { "model": self, "init_infected": init_infected }) # Generate random location, add agent to grid and scheduler for i in range(pop_size): this_neighbourhood = self.random.randint( 0, len(neighbourhood_agents) - 1) # Region where agent starts center_x, center_y = neighbourhood_agents[ this_neighbourhood].shape.centroid.coords.xy this_bounds = neighbourhood_agents[this_neighbourhood].shape.bounds spread_x = int( this_bounds[2] - this_bounds[0]) # Heuristic for agent spread in region spread_y = int(this_bounds[3] - this_bounds[1]) this_x = center_x[0] + self.random.randint(0, spread_x) - spread_x / 2 this_y = center_y[0] + self.random.randint(0, spread_y) - spread_y / 2 this_person = ac_population.create_agent(Point(this_x, this_y), "P" + str(i)) self.grid.add_agents(this_person) self.schedule.add(this_person) # Add the neighbourhood agents to schedule AFTER person agents, # to allow them to update their color by using BaseScheduler for agent in neighbourhood_agents: self.schedule.add(agent) self.datacollector.collect(self) def reset_counts(self): self.counts = { "susceptible": 0, "infected": 0, "recovered": 0, "dead": 0, "safe": 0, "hotspot": 0, } def step(self): """Run one step of the model.""" self.steps += 1 self.reset_counts() self.schedule.step() self.grid._recreate_rtree( ) # Recalculate spatial tree, because agents are moving self.datacollector.collect(self) # Run until no one is infected if self.counts["infected"] == 0: self.running = False