Exemple #1
0
    def __init__(self, env, name, infection_timestamp, household, workplace, age=35, rho=0.3, gamma=0.21, symptoms=None,
                 test_results=None):
        self.env = env
        self.events = []
        self.name = name
        self.age = _get_random_age()

        # probability of being asymptomatic is basically 50%, but a bit less if you're older
        # and a bit more if you're younger
        self.asymptomatic = np.random.rand() > (BASELINE_P_ASYMPTOMATIC - (self.age - 50) * 0.5) / 100
        self.incubation_days = _draw_random_discreet_gaussian(AVERAGE_INCUBATION_DAYS, SCALE_INCUBATION_DAYS)

        self.household = household
        self.workplace = workplace
        self.location = household
        self.rho = rho
        self.gamma = gamma

        self.action = Human.actions['at_home']
        self.visits = Visits()
        self.travelled_recently = np.random.rand() > 0.9

        # &carefullness
        if np.random.rand() < P_CAREFUL_PERSON:
            self.carefullness = round(np.random.normal(75, 10))
        else:
            self.carefullness = round(np.random.normal(35, 10))

        age_modifier = 1
        if self.age > 40 or self.age < 12:
            age_modifier = 2
        self.has_cold = np.random.rand() < P_COLD * age_modifier
        self.has_flu = np.random.rand() < P_FLU * age_modifier
        self.has_app = np.random.rand() < (P_HAS_APP / age_modifier) + (self.carefullness / 2)

        # Indicates whether this person will show severe signs of illness.
        self.infection_timestamp = infection_timestamp
        self.really_sick = self.is_sick and random.random() >= 0.9
        self.never_recovers = random.random() >= 0.99

        # habits
        self.avg_shopping_time = _draw_random_discreet_gaussian(AVERAGE_SHOP_TIME_MINUTES, SCALE_SHOP_TIME_MINUTES)
        self.scale_shopping_time = _draw_random_discreet_gaussian(AVG_SCALE_SHOP_TIME_MINUTES,
                                                                  SCALE_SCALE_SHOP_TIME_MINUTES)

        self.avg_exercise_time = _draw_random_discreet_gaussian(AVG_EXERCISE_MINUTES, SCALE_EXERCISE_MINUTES)
        self.scale_exercise_time = _draw_random_discreet_gaussian(AVG_SCALE_EXERCISE_MINUTES,
                                                                  SCALE_SCALE_EXERCISE_MINUTES)

        self.avg_working_hours = _draw_random_discreet_gaussian(AVG_WORKING_HOURS, SCALE_WORKING_HOURS)
        self.scale_working_hours = _draw_random_discreet_gaussian(AVG_SCALE_WORKING_HOURS, SCALE_SCALE_WORKING_HOURS)

        self.avg_misc_time = _draw_random_discreet_gaussian(AVG_MISC_MINUTES, SCALE_MISC_MINUTES)
        self.scale_misc_time = _draw_random_discreet_gaussian(AVG_SCALE_MISC_MINUTES, SCALE_SCALE_MISC_MINUTES)

        # TODO: multiple possible days and times & limit these activities in a week
        self.shopping_days = np.random.choice(range(7))
        self.shopping_hours = np.random.choice(range(7, 20))

        self.exercise_days = np.random.choice(range(7))
        self.exercise_hours = np.random.choice(range(7, 20))

        self.work_start_hour = np.random.choice(range(7, 12))
Exemple #2
0
def run_simu(n_stores=None,
             n_people=None,
             n_parks=None,
             n_misc=None,
             init_percent_sick=0,
             store_capacity=30,
             misc_capacity=30,
             start_time=datetime.datetime(2020, 2, 28, 0, 0),
             simulation_days=10,
             outfile=None,
             print_progress=False,
             seed=0,
             Human=None):

    if Human is None:
        from simulator import Human

    rng = np.random.RandomState(seed)
    env = Env(start_time)
    city_limit = ((0, 1000), (0, 1000))
    total_area = (city_limit[0][1] - city_limit[0][0]) * (city_limit[1][1] -
                                                          city_limit[1][0])
    area_dict = {
        'store':
        _get_random_area('store', n_stores, total_area, rng),
        'park':
        _get_random_area('park', n_parks, total_area, rng),
        'misc':
        _get_random_area('misc', n_misc, total_area, rng),
        'household':
        _get_random_area('household', int(n_people / 2), total_area, rng),
        'workplace':
        _get_random_area('workplace', int(n_people / 30), total_area, rng)
    }

    stores = [
        Location(env,
                 rng,
                 capacity=_draw_random_discreet_gaussian(
                     store_capacity, int(0.5 * store_capacity), rng),
                 cont_prob=0.6,
                 location_type='store',
                 name=f'store{i}',
                 area=area_dict['store'][i],
                 lat=rng.randint(*city_limit[0]),
                 lon=rng.randint(*city_limit[1]),
                 surface_prob=[0.1, 0.1, 0.3, 0.2, 0.3])
        for i in range(n_stores)
    ]

    parks = [
        Location(env,
                 rng,
                 cont_prob=0.05,
                 name=f'park{i}',
                 area=area_dict['park'][i],
                 location_type='park',
                 lat=rng.randint(*city_limit[0]),
                 lon=rng.randint(*city_limit[1]),
                 surface_prob=[0.7, 0.05, 0.05, 0.1, 0.1])
        for i in range(n_parks)
    ]
    households = [
        Location(env,
                 rng,
                 cont_prob=1,
                 name=f'household{i}',
                 location_type='household',
                 area=area_dict['household'][i],
                 lat=rng.randint(*city_limit[0]),
                 lon=rng.randint(*city_limit[1]),
                 surface_prob=[0.05, 0.05, 0.05, 0.05, 0.8])
        for i in range(int(n_people / 2))
    ]
    workplaces = [
        Location(env,
                 rng,
                 cont_prob=0.3,
                 name=f'workplace{i}',
                 location_type='workplace',
                 area=area_dict['workplace'][i],
                 lat=rng.randint(*city_limit[0]),
                 lon=rng.randint(*city_limit[1]),
                 surface_prob=[0.1, 0.1, 0.3, 0.2, 0.3])
        for i in range(int(n_people / 30))
    ]
    miscs = [
        Location(env,
                 rng,
                 cont_prob=1,
                 capacity=_draw_random_discreet_gaussian(
                     misc_capacity, int(0.5 * misc_capacity), rng),
                 name=f'misc{i}',
                 area=area_dict['misc'][i],
                 location_type='misc',
                 lat=rng.randint(*city_limit[0]),
                 lon=rng.randint(*city_limit[1]),
                 surface_prob=[0.1, 0.1, 0.3, 0.2, 0.3]) for i in range(n_misc)
    ]

    humans = [
        Human(env=env,
              name=i,
              rng=rng,
              age=_get_random_age(rng),
              infection_timestamp=start_time
              if i < n_people * init_percent_sick else None,
              household=rng.choice(households),
              workplace=rng.choice(workplaces)) for i in range(n_people)
    ]

    city = City(stores=stores, parks=parks, humans=humans, miscs=miscs)
    monitors = [EventMonitor(f=120), SEIRMonitor(f=1440)]

    extra_info = {}
    extra_info['init_percent_sick'] = init_percent_sick
    extra_info['initial_states'] = [
        'infected' if i < n_people * init_percent_sick else 'not_infected'
        for i in range(n_people)
    ]
    extra_info['recovery_probs'] = [1.0 / h.recovery_days for h in humans]
    import json
    with open('extra_info.json', 'w') as f:
        json.dump(extra_info, f)

    # run the simulation
    if print_progress:
        monitors.append(TimeMonitor(60))

    for human in humans:
        env.process(human.run(city=city))

    for m in monitors:
        env.process(m.run(env, city=city))
    env.run(until=simulation_days * 24 * 60 / TICK_MINUTE)
    return monitors
    def __init__(self,
                 env,
                 name,
                 age,
                 rng,
                 infection_timestamp,
                 household,
                 workplace,
                 rho=0.3,
                 gamma=0.21,
                 symptoms=[],
                 test_results=None):
        self.env = env
        self.events = []
        self.name = name
        self.rng = rng

        self.age = _get_random_age(self.rng)
        self.sex = _get_random_sex(self.rng)
        self.preexisting_conditions = _get_preexisting_conditions(
            self.age, self.sex, self.rng)

        self.household = household
        self.workplace = workplace
        self.location = household
        self.rho = rho
        self.gamma = gamma

        self.visits = Visits()
        self.travelled_recently = self.rng.rand() > 0.9

        # &carefullness
        if self.rng.rand() < P_CAREFUL_PERSON:
            self.carefullness = round(self.rng.normal(55, 10)) + self.age / 2
        else:
            self.carefullness = round(self.rng.normal(25, 10)) + self.age / 2

        age_modifier = 1
        if self.age > 40 or self.age < 12:
            age_modifier = 2
        self.has_cold = self.rng.rand() < P_COLD * age_modifier
        self.has_flu = self.rng.rand() < P_FLU * age_modifier
        self.has_app = self.rng.rand() < (P_HAS_APP / age_modifier) + (
            self.carefullness / 2)
        self.incubation_days = _draw_random_discreet_gaussian(
            AVG_INCUBATION_DAYS, SCALE_INCUBATION_DAYS, self.rng)

        # Indicates whether this person will show severe signs of illness.
        self.infection_timestamp = infection_timestamp
        self.recovered_timestamp = datetime.datetime.min
        self.really_sick = self.is_exposed and self.rng.random() >= 0.9
        self.extremely_sick = self.really_sick and self.rng.random(
        ) >= 0.7  # &severe; 30% of severe cases need ICU
        self.never_recovers = self.rng.random() >= 0.99

        # &symptoms, &viral-load
        # probability of being asymptomatic is basically 50%, but a bit less if you're older
        # and a bit more if you're younger
        self.is_asymptomatic = self.rng.rand() > (BASELINE_P_ASYMPTOMATIC -
                                                  (self.age - 50) * 0.5) / 100
        self.asymptomatic_infection_ratio = 0.0
        if self.is_asymptomatic:
            self.asymptomatic_infection_ratio = ASYMPTOMATIC_INFECTION_RATIO  # draw a beta with the distribution in documents
        self.recovery_days = _draw_random_discreet_gaussian(
            AVG_RECOVERY_DAYS, SCALE_RECOVERY_DAYS,
            self.rng)  # make it IQR &recovery
        self.viral_load_plateau_height, self.viral_load_plateau_start, self.viral_load_plateau_end, self.viral_load_recovered = _sample_viral_load_piecewise(
            rng, age=age)
        self.all_symptoms_array = _get_all_symptoms_array(
            np.ndarray.item(self.viral_load_plateau_start),
            np.ndarray.item(self.viral_load_plateau_end),
            np.ndarray.item(self.viral_load_recovered),
            age=self.age,
            incubation_days=self.incubation_days,
            really_sick=self.really_sick,
            extremely_sick=self.extremely_sick,
            rng=self.rng,
            preexisting_conditions=self.preexisting_conditions)

        # counters and memory
        self.r0 = []
        self.has_logged_symptoms = False
        self.has_logged_test = False
        self.n_infectious_contacts = 0
        self.last_state = self.state

        # habits
        self.avg_shopping_time = _draw_random_discreet_gaussian(
            AVG_SHOP_TIME_MINUTES, SCALE_SHOP_TIME_MINUTES, self.rng)
        self.scale_shopping_time = _draw_random_discreet_gaussian(
            AVG_SCALE_SHOP_TIME_MINUTES, SCALE_SCALE_SHOP_TIME_MINUTES,
            self.rng)

        self.avg_exercise_time = _draw_random_discreet_gaussian(
            AVG_EXERCISE_MINUTES, SCALE_EXERCISE_MINUTES, self.rng)
        self.scale_exercise_time = _draw_random_discreet_gaussian(
            AVG_SCALE_EXERCISE_MINUTES, SCALE_SCALE_EXERCISE_MINUTES, self.rng)

        self.avg_working_hours = _draw_random_discreet_gaussian(
            AVG_WORKING_MINUTES, SCALE_WORKING_MINUTES, self.rng)
        self.scale_working_hours = _draw_random_discreet_gaussian(
            AVG_SCALE_WORKING_MINUTES, SCALE_SCALE_WORKING_MINUTES, self.rng)

        self.avg_misc_time = _draw_random_discreet_gaussian(
            AVG_MISC_MINUTES, SCALE_MISC_MINUTES, self.rng)
        self.scale_misc_time = _draw_random_discreet_gaussian(
            AVG_SCALE_MISC_MINUTES, SCALE_SCALE_MISC_MINUTES, self.rng)

        #getting the number of shopping days and hours from a distribution
        self.number_of_shopping_days = _draw_random_discreet_gaussian(
            AVG_NUM_SHOPPING_DAYS, SCALE_NUM_SHOPPING_DAYS, self.rng)
        self.number_of_shopping_hours = _draw_random_discreet_gaussian(
            AVG_NUM_SHOPPING_HOURS, SCALE_NUM_SHOPPING_HOURS, self.rng)

        #getting the number of exercise days and hours from a distribution
        self.number_of_exercise_days = _draw_random_discreet_gaussian(
            AVG_NUM_EXERCISE_DAYS, SCALE_NUM_EXERCISE_DAYS, self.rng)
        self.number_of_exercise_hours = _draw_random_discreet_gaussian(
            AVG_NUM_EXERCISE_HOURS, SCALE_NUM_EXERCISE_HOURS, self.rng)

        #Multiple shopping days and hours
        self.shopping_days = self.rng.choice(range(7),
                                             self.number_of_shopping_days)
        self.shopping_hours = self.rng.choice(range(7, 20),
                                              self.number_of_shopping_hours)

        #Multiple exercise days and hours
        self.exercise_days = self.rng.choice(range(7),
                                             self.number_of_exercise_days)
        self.exercise_hours = self.rng.choice(range(7, 20),
                                              self.number_of_exercise_hours)

        #Limiting the number of hours spent shopping per week
        self.max_shop_per_week = _draw_random_discreet_gaussian(
            AVG_MAX_NUM_SHOP_PER_WEEK, SCALE_MAX_NUM_SHOP_PER_WEEK, self.rng)
        self.count_shop = 0

        #Limiting the number of hours spent exercising per week
        self.max_exercise_per_week = _draw_random_discreet_gaussian(
            AVG_MAX_NUM_EXERCISE_PER_WEEK, SCALE_MAX_NUM_EXERCISE_PER_WEEK,
            self.rng)
        self.count_exercise = 0

        self.work_start_hour = self.rng.choice(range(7, 12))