Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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()
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
    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)
Exemplo n.º 5
0
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
Exemplo n.º 6
0
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()
Exemplo n.º 7
0
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)
Exemplo n.º 8
0
    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()
Exemplo n.º 9
0
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
Exemplo n.º 10
0
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
Exemplo n.º 11
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,
                 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)
Exemplo n.º 12
0
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
Exemplo n.º 13
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()
Exemplo n.º 14
0
    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)
Exemplo n.º 15
0
    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(
Exemplo n.º 16
0
    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)
Exemplo n.º 17
0
    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)
Exemplo n.º 18
0
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
Exemplo n.º 19
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)
Exemplo n.º 20
0
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
Exemplo n.º 21
0
    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)
Exemplo n.º 22
0
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