Ejemplo n.º 1
0
    def place_agents_on_the_field(self, width: uint, length: uint, seed: int,
                                  susceptible_share: float,
                                  infected_share: float):
        """Inital placements of agents on the field.
        Author: Benjamin Eder, Konstantin Schlosser"""
        if self.__grid is None:
            self.init_empty_grid(width, length)
        np.random.seed(seed)
        self.rs = np.random.RandomState(
            np.random._mt19937.MT19937(
                np.random._bit_generator.SeedSequence(seed)))

        total_num_of_fields = width * length

        # Fill shares randomly in the underlying data
        choice = self.rs.choice(total_num_of_fields,
                                int(
                                    np.round(
                                        (susceptible_share + infected_share) *
                                        total_num_of_fields)),
                                replace=False)
        susceptible_count = int(round(susceptible_share * total_num_of_fields))

        for i in choice[:susceptible_count]:
            row = uint(i // width)
            col = uint(i % length)
            self.spawn_agent(GridPos(row, col), AgentState.SUSCEPTIBLE)

        for i in choice[susceptible_count:]:
            row = uint(i // width)
            col = uint(i % length)
            self.spawn_agent(GridPos(row, col), AgentState.INFECTIVE)
Ejemplo n.º 2
0
def get_free_pos_limited(
    grid,
    pos: GridPos,
    radius: int = 1,
    metric: EnvironmentMetric = EnvironmentMetric.EUCLIDEAN,
) -> GridPos:
    """
    Get a free position on the grid only [radius] from the passed position.
    Autor: Benjamin Eder
    :param grid:
    :param pos:
    :param radius:
    :param metric:
    :return:
    """
    possible_positions = []

    env_size = radius * 2 + 1

    grid_size = grid.get_size()

    cur_row = int(pos.row())
    cur_col = int(pos.col())

    if metric == EnvironmentMetric.MANHATTAN:
        for r in range(0, env_size):
            offset = abs(radius - r)
            check_row = cur_row - radius + r
            for c in range(offset, env_size - offset):
                check_column = cur_col - radius + c
                possible_positions.append((check_row, check_column))
    elif metric == EnvironmentMetric.EUCLIDEAN:
        for r in range(0, env_size):
            check_row = cur_row - radius + r
            for c in range(0, env_size):
                check_column = cur_col - radius + c
                distance = np.round(np.sqrt((radius - r)**2 + (radius - c)**2))
                if 0 < distance <= radius:
                    possible_positions.append((check_row, check_column))
    else:
        raise ValueError('Metric not implemented')

    # Filter positions that are no more in the Grid or are already used
    possible_positions = list(
        filter(
            lambda pos: 0 <= pos[0] < grid_size and 0 <= pos[1] < grid_size and
            (pos[0] != cur_row or pos[1] != cur_col) and not grid.is_occupied(
                GridPos(np.uint(pos[0]), np.uint(pos[1]))),
            possible_positions))

    if len(possible_positions) == 0:
        raise ValueError("No free positions available. ")

    random_choice = random.choice(possible_positions)
    return GridPos(np.uint(random_choice[0]), np.uint(random_choice[1]))
Ejemplo n.º 3
0
 def update_gui_state(self, grid_pos: GridPos,
                      agent_state: AgentState) -> None:
     self.trigger_gui_event(
         Events.AGENT_CHANGE_GUI, {
             "row": grid_pos.row(),
             "col": grid_pos.col(),
             "state": agent_state.value
         })
     self.__logger.debug(
         f"Agent update, at position {grid_pos.row()},{grid_pos.col()}, new state: {agent_state}"
     )
Ejemplo n.º 4
0
    def execute(self, agent: Agent, state: SimState) -> None:
        """
        Isolate (Remove from Grid) a given share of infected people for the sickness-duration.
        Afterwards they need to be added again to the Grid as removed/dead/immune.
        """
        if agent.is_quarantined():
            if agent.state() is AgentState.DEAD or agent.state() is AgentState.IMMUNE or agent.state() is AgentState.REMOVED:

                grid = agent.grid()
                for row in range(grid.get_size()):
                    for col in range(grid.get_size()):
                        grid_pos = GridPos(np.uint(row), np.uint(col))
                        if not grid.is_occupied(grid_pos):
                            grid.set_agent(agent, grid_pos)
                            agent.set_pos(grid_pos)
                            agent.set_quarantined(False)
                            agent.grid().get_quarantinedAgents().remove(agent)
                            state.add_to_quarantined_count(-1)
                            return

        else:
            isolate_share = state.quarantine_share()  # Share of infected cells to isolate
            infected = state.infected_count()

            if agent.state() == AgentState.INFECTIVE and state.get_quarantined_count() < isolate_share * (
                    infected + state.get_quarantined_count()):
                agent.set_quarantined(True)
                agent.grid().get_quarantinedAgents().append(agent)
                agent.grid().set_agent(None, agent.get_pos())
                agent.get_scheduler().update_gui_state(agent.get_pos(), AgentState.EMPTY)
                state.add_to_quarantined_count(1)
Ejemplo n.º 5
0
def get_free_pos(grid) -> GridPos:
    """
    Returns a free position on the field, if there is one.
    Author: Beil Benedikt
    :param grid: Field, where a free position is to be searched.
    :return: A free prosition on the field, if there is one.
    """
    if grid.is_fully_occupied():
        raise Exception(
            "The field is completely occupied. The agent cannot move. ")

    rand_x = np.uint(np.random.randint(low=0, high=grid.get_size()))
    rand_y = np.uint(np.random.randint(low=0, high=grid.get_size()))
    while grid.is_occupied(GridPos(rand_x, rand_y)):
        rand_x = np.uint(np.random.randint(low=0, high=grid.get_size()))
        rand_y = np.uint(np.random.randint(low=0, high=grid.get_size()))

    return GridPos(rand_x, rand_y)
Ejemplo n.º 6
0
 def is_fully_occupied(self) -> bool:
     """
     Author: Beil Benedikt
     :return: Whether the whole grid is occupied
     """
     for i in range(self.get_size()):
         for j in range(self.get_size()):
             if not self.is_occupied(GridPos(uint(i), uint(j))):
                 return False
     return True
Ejemplo n.º 7
0
 def __reset(self, state: SimState) -> None:
     if self.get_grid() is not None:
         self.get_grid().remove_listeners()
     new_grid = Grid(self.__scheduler)
     new_grid.reset(state)
     self.set_grid(new_grid)
     total_count = 0
     for row in range(self.__grid.get_size()):
         for col in range(self.__grid.get_size()):
             if self.__grid.get_agent(GridPos(uint(row),
                                              uint(col))) is not None:
                 total_count += 1
     state.set_beginning_total_count(total_count)
Ejemplo n.º 8
0
 def test_is_occupied(self):
     sut = self.__get_sut()
     sut.init_empty_grid(uint(100), uint(100))
     test_pos = GridPos(uint(0), uint(0))
     sut.spawn_agent(test_pos, AgentState.SUSCEPTIBLE)
     self.assertTrue(sut.is_occupied(test_pos))
     self.assertFalse(sut.is_occupied(GridPos(uint(0), uint(1))))
     self.assertFalse(sut.is_occupied(GridPos(uint(1), uint(0))))
     self.assertFalse(sut.is_occupied(GridPos(uint(1), uint(1))))
     self.assertFalse(sut.is_occupied(GridPos(uint(99), uint(99))))
     self.assertFalse(sut.is_occupied(GridPos(uint(99), uint(0))))
     self.assertFalse(sut.is_occupied(GridPos(uint(0), uint(99))))
Ejemplo n.º 9
0
    def execute(self, agent: Agent, state: SimState) -> None:
        if agent.is_quarantined():
            return

        if agent.state() is AgentState.INFECTIVE or AgentState.INCUBATION:
            infection_radius = state.infection_env_radius()
            infection_env_size = infection_radius * 2 + 1
            size = agent.grid().get_size()
            check_list = list()
            grid_pos = agent.get_pos()
            x = grid_pos.row()
            y = grid_pos.col()

            if state.infection_env_metric() == EnvironmentMetric.MANHATTAN:
                for r in range(0, infection_env_size):
                    offset = abs(infection_radius - r)
                    check_row = y - infection_radius + r
                    for c in range(offset, infection_env_size - offset):
                        check_column = x - infection_radius + c
                        check_list.append((check_column, check_row))

            elif state.infection_env_metric() == EnvironmentMetric.EUCLIDEAN:
                for r in range(0, infection_env_size):
                    check_row = y - infection_radius + r
                    for c in range(0, infection_env_size):
                        check_column = x - infection_radius + c
                        distance = np.round(np.sqrt((infection_radius - r) ** 2 + (infection_radius - c) ** 2))
                        if 0 < distance <= infection_radius:
                            check_list.append((check_column, check_row))

            else:
                raise ValueError('Metric not implemented')

            check_list = list(filter(lambda pos: 0 <= pos[0] < size and 0 <= pos[1] < size, check_list))

            for check_pos in check_list:
                to_check = agent.grid().get_agent(GridPos(np.uint(check_pos[0]), np.uint(check_pos[1])))
                if to_check is not None and to_check.state() is AgentState.SUSCEPTIBLE:
                    if np.random.random() < state.infection_prob():
                        if state.incubation_period_enabled():
                            to_check.set_state(AgentState.INCUBATION)
                        else:
                            to_check.set_state(AgentState.INFECTIVE)
                        agent.update_infected_count()
Ejemplo n.º 10
0
def calc_effective_reproduction_number(
        grid: Grid,
        remove_probability=0.6,
        infection_probability=0.2,
        infection_radius=1,
        infection_metric=EnvironmentMetric.MANHATTAN
) -> float:
    """
    Calculate the effective reproduction number R
    """

    mean_infection_duration = 1 / remove_probability

    size = grid.get_size()
    infection_env_size = infection_radius * 2 + 1

    # Find all infected cells
    infection_counts = []
    for row in range(size):
        for column in range(size):
            agent = grid.get_agent(GridPos(np.uint(row), np.uint(column)))
            if agent is not None and agent.state() is AgentState.INFECTIVE:
                # Is an infected cell -> Count number of infectable (susceptible) cells in the near environment
                infectable_count = 0

                if infection_metric == EnvironmentMetric.MANHATTAN:
                    for r in range(0, infection_env_size):
                        offset = abs(infection_radius - r)
                        check_row = row - infection_radius + r
                        for c in range(offset, infection_env_size - offset):
                            check_column = column - infection_radius + c

                            if check_row < 0 or check_column < 0 or check_row >= size or check_column >= size:
                                continue

                            other_agent = grid.get_agent(GridPos(np.uint(check_row), np.uint(check_column)))
                            if other_agent is not None and other_agent.state() is AgentState.SUSCEPTIBLE:
                                infectable_count += 1
                elif infection_metric == EnvironmentMetric.EUCLIDEAN:
                    for r in range(0, infection_env_size):
                        check_row = row - infection_radius + r
                        for c in range(0, infection_env_size):
                            check_column = column - infection_radius + c

                            if check_row < 0 or check_column < 0 or check_row >= size or check_column >= size:
                                continue

                            distance = np.round(
                                np.sqrt((infection_radius - r) ** 2 + (infection_radius - c) ** 2))
                            if distance > 0 and distance <= infection_radius:
                                other_agent = grid.get_agent(GridPos(np.uint(check_row), np.uint(check_column)))
                                if other_agent is not None and other_agent.state() is AgentState.SUSCEPTIBLE:
                                    infectable_count += 1

                # Check how many people already have been infected by the person
                already_infected_count = agent.infected_count()

                # Check how many days the agent is already infected
                already_infected_time = agent.sick_days()

                # Estimate how many more days the agent will be infected
                infection_time_estimate = max(round(mean_infection_duration - already_infected_time), 1)  # The agent will live at least one more day

                # Estimate how many more people are going to be infected by that agent
                infection_estimate = infection_time_estimate * infectable_count * infection_probability

                # Sum up all the actual and estimated infection by that agent
                total_estimated_infections = already_infected_count + infection_estimate

                infection_counts.append(total_estimated_infections)

    return np.array(infection_counts).mean() if len(infection_counts) > 0 else 0
Ejemplo n.º 11
0
 def set_agent(self, agent: Agent, grid_pos: GridPos) -> None:
     self.__grid[grid_pos.row()][grid_pos.col()] = agent
Ejemplo n.º 12
0
 def get_agent(self, grid_pos: GridPos) -> Agent:
     return self.__grid[grid_pos.row()][grid_pos.col()]