コード例 #1
0
    def __init__(
            self, infectious_rate_distribution: Disease_Property_Distribution,
            immunity_distribution: Disease_Property_Distribution,
            disease_period_distribution: Disease_Property_Distribution,
            death_probability_distribution: Disease_Property_Distribution,
            incubation_period_distribution: Disease_Property_Distribution):
        """Initialize a disease properties object and create infectious and immunity
        dictionaries.

        Args:
            infectious_rate_distribution (Disease_Property_Distribution): The
            distribution explaining infectious rate.

            immunity_distribution (Disease_Property_Distribution): The distribution
            of people's immunity.

            disease_period_distribution (Disease_Property_Distribution): This holds
            the distribution of infectious period.

            incubation_period_distribution (Disease_Property_Distribution): The distribution
            of incubation period.

            death_probability_distribution (Disease_Property_Distribution): This
            determines the probability that the virus kills someone.
        """
        self.immunity_distribution = immunity_distribution
        self.infectious_rate_distribution = infectious_rate_distribution
        self.disease_period_distribution = disease_period_distribution
        self.death_probability_distribution = death_probability_distribution
        self.incubation_period_distribution = incubation_period_distribution

        self.infectious_rate_dict: Dict[int, float] = {}
        self.immunity_dict: Dict[int, float] = {}

        logger.info('Disease Properties generated')
コード例 #2
0
    def display_population_statistics(population_generator):
        """Print population statistics on the terminal.

        Args:
            population_generator (Population_Generator): The population generator class consisting of population data.
        """
        # family patterns
        patterns_table = Texttable()
        patterns = population_generator.family_pattern_probability_dict
        for pattern in patterns:
            members_count = pattern.number_of_members
            genders = ['Male' if gender else 'Female' for gender in pattern.genders]
            patterns_table.add_rows([['Family Pattern Probability', 'Number of Members', 'Genders'],
                                     [patterns[pattern], members_count, genders]])

        logger.info(f'\n{patterns_table.draw()}')

        # community types
        types_table = Texttable()
        types = population_generator.community_types
        for community_type in types:
            name = community_type.name
            communities_count = community_type.number_of_communities
            sub_community_types = [sct.name for sct in community_type.sub_community_types]
            types_table.add_rows([['Community Type', 'Number of Communities', 'Sub-community Types'],
                                  [name, communities_count, sub_community_types]])

        logger.info(f'\n{types_table.draw()}')
コード例 #3
0
def parse_optimization_trials_result(
        folder_name: str = 'trials') -> List[hyperopt.base.Trials]:
    """Extract trial objects from pickle files.

    From the documentation of trials we have that:
        trials.trials - a list of dictionaries representing
        everything about the search.
        trials.results - a list of dictionaries returned by
        'objective' during the search.
        trials.losses() - a list of losses (float for each 'ok' trial)
        trials.statuses() - a list of status strings

    Args:
        folder_name (str, optional): The name of trials folder. Defaults to trials.

    Returns:
        List[hyperopt.base.Trials]: The parsed trial obejects.

    """
    trials_list: List[hyperopt.base.Trials] = list()

    logger.info(f'Entering the {folder_name} directory')

    for file_name in os.listdir(folder_name):
        with open(os.path.join(folder_name, file_name), 'rb') as trial_file:
            trials_list.append(pickle.load(trial_file))

    return trials_list
コード例 #4
0
    def display_simulator_statistics(simulator):
        """Print the simulator data on the terminal.

        Args:
            simulator (Simulator): The simulator object which its data is printed.
        """
        t = Texttable()
        t.add_rows([['Simulator', 'Data'],
                    ['Start Time', simulator.end_time.init_date_time],
                    ['End Time', simulator.end_time.get_utc_time()],
                    ['Spread Period', simulator.spread_period.get_minutes()],
                    ['Database', simulator.database_name]])

        logger.info(f'\n{t.draw()}')
コード例 #5
0
ファイル: time_simulator.py プロジェクト: amehrjou/Pyfectious
    def generate_model(self, is_parallel: bool = False, show_progress: bool = True):
        """Generates a the simulation model, including the people, graph, families,
        and communities.

        Args:
            is_parallel (bool): If true, the function uses multiprocessing to boost
            the computations. Otherwise, the method runs in normal single processing
            mode.

            show_progress (bool, optional): Whether to show the progress bar or not.
            Defaults to True.
        """
        self.people, self.graph, self.families, self.communities = \
            self.population_generator.generate_population(is_parallel, show_progress)

        logger.info('Simulation model generated')
コード例 #6
0
    def take_action(self, simulator, end_time: Time):
        """Start the action that the commands is designed for.

        Args:
            simulator (Simulator): The main simulator object which is passed to
            this command.



            end_time (Time): The final time of the simulation.
        """
        if self.condition.is_satisfied(simulator, end_time):
            logger.info(f'Command executed: {self.__class__.__name__}')

            for person in simulator.people:
                person.unquarantine()
コード例 #7
0
    def display_spread_statistics(simulator):
        """Print the parameters related to the spread like R0 of a completed simulation.

        R0: At the beginning of an epidemics the R0 value describes how many other people
        an infected person will infect on average.

        Args:
            simulator (Simulator): The simulator objects.
        """
        t = Texttable()
        t.add_rows([['Parameter', 'Value'],
                    ['R0', simulator.end_time.init_date_time],
                    ['R effective', simulator.end_time.get_utc_time()],
                    ['Spread Period', simulator.spread_period.get_minutes()],
                    ['Database', simulator.database_name]])

        logger.info(f'\n{t.draw()}')
コード例 #8
0
    def take_action(self, simulator, end_time: Time):
        """Start the action that the commands is designed for.

        Args:
            simulator (Simulator): The main simulator object which is passed to
            this command.



            end_time (Time): The final time of the simulation.
        """
        if self.condition.is_satisfied(simulator, end_time):
            logger.info(f'Command executed: {self.__class__.__name__}')

            for family in simulator.families:
                if family.id_number in self.ids:
                    logger.debug(f'Family unquarantined: {family.id_number}')
                    family.unquarantine(simulator.people)
コード例 #9
0
    def take_action(self, simulator, end_time: Time):
        """Start the action that the commands is designed for.

        Args:
            simulator (Simulator): The main simulator object which is passed to
            this command.



            end_time (Time): The final time of the simulation.
        """
        if self.condition.is_satisfied(simulator, end_time):
            logger.info(f'Command executed: {self.__class__.__name__}')

            for person in simulator.people:
                if person.infection_status is Infection_Status.CONTAGIOUS or \
                        person.infection_status is Infection_Status.INCUBATION:
                    logger.debug(f'Person unquarantined: {person.id_number}')
                    person.unquarantine()
コード例 #10
0
ファイル: time_simulator.py プロジェクト: amehrjou/Pyfectious
    def save_model(self, model_name: str):
        """Save the simulation model generated in generate model method for later use.

        This function saves the model in a pickle file located in the data/pickle
        folder.

        Warning: Using save model will change the reference of the objects, and leads to
        creation of different communities, people, families, etc. Only use it once to
        maintain consistency of the references.

        Args:
            model_name (str): The name of the pickle file to be saved.
        """
        if basename(os.path.abspath(os.path.join(os.getcwd(), os.pardir))) == 'Pyfectious':
            path = os.path.join(os.getcwd(), os.pardir, 'data', 'pickle', model_name)
        elif basename(os.getcwd()) == 'Pyfectious':
            path = os.path.join(os.getcwd(), 'data', 'pickle', model_name)
        else:
            logger.warning('Failed to save model, change directory to src, example, or \
                project main directory and try again!')
            return

        os.makedirs(path, exist_ok=True)

        graph_path = os.path.join(path, 'graph.pickle')
        people_path = os.path.join(path, 'people.pickle')
        families_path = os.path.join(path, 'families.pickle')
        communities_path = os.path.join(path, 'communities.pickle')

        with open(people_path, 'wb') as f:
            pickle.dump(self.people, f)

        with open(graph_path, 'wb') as f:
            pickle.dump(self.graph, f)

        with open(families_path, 'wb') as f:
            pickle.dump(self.families, f)

        with open(communities_path, 'wb') as f:
            pickle.dump(self.communities, f)

        logger.info(f'Simulator model {model_name} saved')
コード例 #11
0
    def take_action(self, simulator, end_time: Time):
        """Start the action that the commands is designed for.

        Args:
            simulator (Simulator): The main simulator object which is passed to
            this command.

            end_time (Time): The final time of the simulation.
        """
        if self.condition.is_satisfied(simulator, end_time):
            logger.info(
                f'Command executed: {self.__class__.__name__}, {self.role_name}'
            )

            for person in simulator.people:
                for community, subcommunity_type_index in person.communities:
                    if self.role_name == community.community_type.sub_community_types[
                            subcommunity_type_index].name:
                        community.community_type.sub_community_types[subcommunity_type_index] \
                            .community_type_role.presence_prob = 1 - self.restriction_ratio
コード例 #12
0
    def display_family_statistics(people: List, families: List):
        """Print the family statistics on the terminal.

        Args:
            people (List[Person]): The people of the simulator that are merged into families.
            families (List[Family]): The families of the simulation environment.
        """
        stat_dict = Statistics.get_family_statistics(people, families)

        total_families = len(families)
        dead = stat_dict[Health_Condition.DEAD]
        is_infected = stat_dict[Health_Condition.IS_INFECTED]
        has_been_infected = stat_dict[Health_Condition.HAS_BEEN_INFECTED]

        t = Texttable()
        t.add_rows([['Families', 'Count'],
                    ['Number of Families', total_families],
                    ['Confirmed (Active + Close)', has_been_infected],
                    ['Total Death Cases', dead],
                    ['Currently Active Cases', is_infected]])
        logger.info(f'\n{t.draw()}')
コード例 #13
0
    def display_people_statistics(simulator):
        """Print the people's statistics table on the terminal

        Args:
            simulator (Simulator): The simulation environment.
        """
        stat_dict = simulator.statistics.get_people_statistics()

        total_people = stat_dict[Health_Condition.ALL]
        dead = stat_dict[Health_Condition.DEAD]
        is_infected = stat_dict[Health_Condition.IS_INFECTED]
        has_been_infected = stat_dict[Health_Condition.HAS_BEEN_INFECTED]

        t = Texttable()
        t.add_rows([['People', 'Count'],
                    ['Population Size', total_people],
                    ['Confirmed (Active + Close)', has_been_infected],
                    ['Total Death Cases', dead],
                    ['Total Recovered', has_been_infected - dead],
                    ['Currently Active Cases', is_infected]])
        logger.info(f'\n{t.draw()}')
コード例 #14
0
    def take_action(self, simulator, end_time: Time):
        """Start the action that the commands is designed for.

        Args:
            simulator (Simulator): The main simulator object which is passed to
            this command.

            end_time (Time): The final time of the simulation.
        """
        if self.condition.is_satisfied(simulator, end_time):
            logger.info(
                f'Command executed: {self.__class__.__name__}, target: {self.community_type_name}'
            )

            for community_type_id in simulator.communities:
                if simulator.communities[community_type_id][
                        0].community_type.name == self.community_type_name:
                    logger.debug(
                        f'Community quarantined: {self.community_type_name}, {self.community_index}'
                    )
                    simulator.communities[community_type_id][
                        self.community_index].unquarantine()
コード例 #15
0
ファイル: time_simulator.py プロジェクト: amehrjou/Pyfectious
    def load_model(self, model_name: str):
        """Load a saved simulation model from the pickle folder.

        This function automatically sets the simulation main entities to
        the data loaded from the pickle file.

        Args:
            model_name (str): The name of the model to be loaded.
        """
        if basename(os.getcwd()) == 'Pyfectious':
            sys.path.insert(1, 'src')
            path = os.path.join(os.getcwd(), 'data', 'pickle', model_name)
        elif basename(os.path.abspath(os.path.join(os.getcwd(), os.pardir))) == 'Pyfectious':
            sys.path.insert(1, os.path.join(os.pardir, 'src'))
            path = os.path.join(os.getcwd(), os.pardir, 'data', 'pickle', model_name)
        else:
            raise FileNotFoundError('Failed to save model, change directory to src, example, or \
                project main directory and try again!')

        graph_path = os.path.join(path, 'graph.pickle')
        people_path = os.path.join(path, 'people.pickle')
        families_path = os.path.join(path, 'families.pickle')
        communities_path = os.path.join(path, 'communities.pickle')

        with open(people_path, 'rb') as f:
            self.people = pickle.load(f)

        with open(graph_path, 'rb') as f:
            self.graph = pickle.load(f)

        with open(families_path, 'rb') as f:
            self.families = pickle.load(f)

        with open(communities_path, 'rb') as f:
            self.communities = pickle.load(f)

        logger.info(f'Simulator model {model_name} loaded')
コード例 #16
0
def quarantine_optimization_function(params, index: int = 0):
    """A sample objective function to quarantine certain roles.

    Args:
        index (int): The index of the running object, if applicable on cluster.
        params (Dict): The set of input parameters dictionary.
    """
    simulator = Parser(folder_name='town_optimization').parse_simulator()
    end_time, spread_period, initialized_infected_ids, commands, observers = \
        Parser(folder_name='town_optimization').parse_simulator_data()

    simulator.load_model('town_optimization')

    commands.clear()
    quarantine_effective_day = 2

    condition_student = Time_Point_Condition(deadline=Time(timedelta(days=quarantine_effective_day)))
    condition_worker = Time_Point_Condition(deadline=Time(timedelta(days=quarantine_effective_day)))
    condition_customer = Time_Point_Condition(deadline=Time(timedelta(days=quarantine_effective_day)))

    commands.append(Restrict_Certain_Roles(condition=condition_student,
                                           role_name='Student',
                                           restriction_ratio=params['student_restriction_ratio']))

    commands.append(Restrict_Certain_Roles(condition=condition_worker,
                                           role_name='Worker',
                                           restriction_ratio=params['worker_restriction_ratio']))

    commands.append(Restrict_Certain_Roles(condition=condition_customer,
                                           role_name='Customer',
                                           restriction_ratio=1.4 - params['worker_restriction_ratio'] - params['student_restriction_ratio']))

    logger.info(f'Restriction ratios are {[(command.role_name, command.restriction_ratio) for command in commands]}')
    logger.info(f'Quarantine starts at day {quarantine_effective_day}')

    simulator.simulate(end_time=Time(delta_time=timedelta(days=20),
                                     init_date_time=datetime.now()),
                       spread_period=spread_period,
                       initialized_infected_ids=initialized_infected_ids,
                       commands=commands,
                       observers=observers,
                       report_statistics=1)

    stats, times = observers[0].get_disease_statistics_during_time(Health_Condition.IS_INFECTED)

    loss = max(stats)
    optimization_index = loss
    logger.info(f'Peak height is {loss}, and parameters are {params}')

    from cluster_utils import save_lists_csv
    save_lists_csv(data_lists=[stats, times],
                   list_names=['statistics', 'time'],
                   file_name='data_node_' + str(index) + '_' + str(optimization_index),
                   folder_name='data_optimization')

    return {'loss': loss, 'params': params, 'status': STATUS_OK}
コード例 #17
0
    def display_disease_characteristics(disease_properties):
        """Print the statistics related to disease in terminal.

        Args:
            disease_properties (Disease_Properties): The disease properties object containing disease information.
        """

        infectious_rate_distribution = disease_properties.infectious_rate_distribution
        immunity_distribution = disease_properties.immunity_distribution
        disease_period_distribution = disease_properties.disease_period_distribution
        death_probability_distribution = disease_properties.death_probability_distribution

        t = Texttable()
        t.add_rows([['Disease Property', 'Distribution Type', 'Parameters'],
                    ['Infectious Rate', infectious_rate_distribution.__class__.__name__,
                     infectious_rate_distribution.parameters_dict],
                    ['Immunity Rate', immunity_distribution.__class__.__name__,
                     immunity_distribution.parameters_dict],
                    ['Disease Period', disease_period_distribution.__class__.__name__,
                     disease_period_distribution.parameters_dict],
                    ['Death Probability', death_probability_distribution.__class__.__name__,
                     death_probability_distribution.parameters_dict]])

        logger.info(f'\n{t.draw()}')
コード例 #18
0
ファイル: time_simulator.py プロジェクト: amehrjou/Pyfectious
    def simulate(self, end_time: Time, spread_period: Time, initialized_infected_ids: List[int],
                 commands: List, observers: List, report_statistics: int = 1, database_name: Tuple = None,
                 show_progress: bool = True):
        """The main simulator function that starts the simulation given a certain criteria.

        The simulation main loop is located inside this function, in addition to collecting
        the observers and commands (policy).

        Args:
            end_time (Time): The simulation end time. Determines the total period
            of the simulation.

            spread_period (Time): The spread period determines the period of running the
            virus spread function.

            initialized_infected_ids (List[int]): A list of infected people at the beginning
            of the simulation.

            commands (List[Command]): A list of actions given to the simulator to contract the
            spread of the virus. The acceptable commands are located in commands.py module.

            observers (List[Observer]): The observer object to record the data from simulation
            into the database.

            report_statistics (int, optional): This parameter determines the degree of statistics
            shown after the simulation concluded. Starting from 0, meaning no statistics at all,
            and goes all the way to 2, where all the available statistics are shown in the console.
            Defaults to 1.

            database_name (Tuple, optional): The name of the database in case a change is required.
            Default to None.

            show_progress (bool, optional): Whether to show the progress bar or not.
            Defaults to True.
        """

        # Initialize simulation
        logger.info('Initializing the simulation')
        self.initialized_infected_ids = initialized_infected_ids
        self.end_time, self.spread_period = end_time, spread_period
        self.commands, self.observers = commands, observers
        self.database_name = database_name
        self.initialize_simulation()

        # Print a log and the progress indicator
        logger.info('Starting the simulation')

        with tqdm(total=self.end_time.get_minutes(), file=sys.stdout, disable=not show_progress) \
                as progress_bar:

            # Simulation main loop
            while Time.check_less(self.clock, self.end_time):

                # Events
                event = heapq.heappop(self.events)
                event.activate(self)

                # Observations
                self.execute_observers()

                # Commands
                self.execute_commands()

                # Update clock
                self.clock.set_minutes(event.minute)

                # Show progress
                progress_bar.update(self.clock.get_minutes() - progress_bar.n)

        logger.info('Simulation completed')

        # Show statistics
        self.statistics.report(self, report_statistics)

        # Database termination
        self.database.commit()
コード例 #19
0
def build_experiment_results_data_dict(
        number_of_experiments: int = 16,
        experiment_name_constant_part: str = 'data_town_',
        folder_name: str = 'data',
        experiment_folder: str = 'cluster_experiment_1',
        add_time: bool = False) -> Dict[int, List[Dict]]:
    """Build a dictionary containing the experiment folders at the first level and the individual
    executions in the second level.

    Note: The function assumes that the data is either stored in the same path as the
    function's execution path, or in the data folder and in the same path.

    TODO: This function needs a huge refactor afterward.

    Args:
        add_time (bool, optional): Add the times to the dictionary separately if required.
        experiment_folder (str, optional): The folder under json to determine the experiment
        configuration sets. Defaults to 'cluster_experiment_1'.

        number_of_experiments (int, optional): The total number of experiment folders in the data.

        experiment_name_constant_part: The beginning string of experiment result folders. Defaults
        to 'data_town_', e.g., data_town_0.

        folder_name(str, optional) The folder name of the experiments. Defaults to 'data'.
        It's also possible to just copy the data into cluster folder.

    Returns:
        Dict[int, List[Dict]]: The major dictionary containing the results and some specifications
        of all the experiments.
    """
    # Change directory to the data folder (if exists)
    if os.path.exists(folder_name):
        os.chdir(folder_name)

    # Build the grand dictionary of data
    towns_data_dict: Dict[int, List[Dict]] = dict()

    for file_index in range(number_of_experiments):
        folder_name = experiment_name_constant_part + str(file_index)
        logger.info(f'Entering the {folder_name} directory')

        single_town_data_list = list()
        for file_name in os.listdir(folder_name):
            data_dict = dict()

            # TODO: change the following lines later.
            data = read_lists_csv(list_names=['statistics', 'time'],
                                  file_name=file_name,
                                  folder_name=folder_name)
            statistics, times = data

            data_dict['statistics'] = statistics[:len(statistics) - 1]
            data_dict['time'] = convert_time_str_to_datetime(
                times[:len(times) - 1])

            if add_time:
                data_dict['simulation_time'] = float(times[-1])
                data_dict['generation_time'] = statistics[-1]

            single_town_data_list.append(data_dict)

        towns_data_dict[file_index] = single_town_data_list

    # Move to cluster directory
    if not os.path.exists('data'):
        os.chdir(os.path.join(os.getcwd(), os.pardir))

    # Use parser to complete the dicts
    for folder_index in towns_data_dict:
        json_parser = Parser(
            os.path.join(experiment_folder, 'town_' + str(folder_index)))
        simulator = json_parser.parse_simulator()

        population_size = simulator.population_generator.population_size
        immunity_distribution_dict = simulator.disease_properties.immunity_distribution.parameters_dict
        infectious_rate_dict = simulator.disease_properties.infectious_rate_distribution.parameters_dict

        for data_dict in towns_data_dict[folder_index]:
            data_dict['population_size'] = population_size
            data_dict[
                'immunity_distribution_dict'] = immunity_distribution_dict
            data_dict['infectious_rate_dict'] = infectious_rate_dict

    return towns_data_dict