Example #1
0
    def initialize_locations(self):
        for location, specs in LOCATION_DISTRIBUTION.items():
            if location in ['household']:
                continue

            n = math.ceil(self.n_people/specs["n"])
            area = _get_random_area(n, specs['area'] * self.total_area, self.rng)
            locs = [self.create_location(specs, location, i, area[i]) for i in range(n)]
            setattr(self, f"{location}s", locs)
Example #2
0
    def initialize_humans(self, Human):
        # allocate humans to houses such that (unsolved)
        # 1. average number of residents in a house is (approx.) 2.6
        # 2. not all residents are below 15 years of age
        # 3. age occupancy distribution follows HUMAN_DSITRIBUTION.residence_preference.house_size

        # current implementation is an approximate heuristic

        # make humans
        count_humans = 0
        house_allocations = {2:[], 3:[], 4:[], 5:[]}
        n_houses = 0
        for age_bin, specs in HUMAN_DISTRIBUTION.items():
            n = math.ceil(specs['p'] * self.n_people)
            ages = self.rng.randint(*age_bin, size=n)

            senior_residency_preference = specs['residence_preference']['senior_residency']

            professions = ['healthcare', 'school', 'others', 'retired']
            p = [specs['profession_profile'][x] for x in professions]
            profession = self.rng.choice(professions, p=p, size=n)

            for i in range(n):
                count_humans += 1
                age = ages[i]

                # residence
                res = None
                if self.rng.random() < senior_residency_preference:
                    res = self.rng.choice(self.senior_residencys)
                # workplace
                if profession[i] == "healthcare":
                    workplace = self.rng.choice(self.hospitals + self.senior_residencys)
                elif profession[i] == 'school':
                    workplace = self.rng.choice(self.schools)
                elif profession[i] == 'others':
                    type_of_workplace = self.rng.choice([0,1,2], p=OTHERS_WORKPLACE_CHOICE, size=1).item()
                    type_of_workplace = [self.workplaces, self.stores, self.miscs][type_of_workplace]
                    workplace = self.rng.choice(type_of_workplace)
                else:
                    workplace = res

                self.humans.append(Human(
                        env=self.env,
                        rng=self.rng,
                        name=count_humans,
                        age=age,
                        household=res,
                        workplace=workplace,
                        profession=profession[i],
                        rho=0.3,
                        gamma=0.21,
                        infection_timestamp=self.start_time if self.rng.random() < self.init_percent_sick else None
                        )
                    )

        # assign houses
        # stores tuples - (location, current number of residents, maximum number of residents allowed)
        remaining_houses = []
        for human in self.humans:
            if human.household is not None:
                continue
            if len(remaining_houses) == 0:
                cap = self.rng.choice(range(1,6), p=HOUSE_SIZE_PREFERENCE, size=1)
                x = self.create_location(LOCATION_DISTRIBUTION['household'], 'household', len(self.households))

                remaining_houses.append((x, cap))

            # get_best_match
            res = None
            for  c, (house, n_vacancy) in enumerate(remaining_houses):
                new_avg_age = (human.age + sum(x.age for x in house.residents))/(len(house.residents) + 1)
                if new_avg_age > MIN_AVG_HOUSE_AGE:
                    res = house
                    n_vacancy -= 1
                    if n_vacancy == 0:
                        remaining_houses = remaining_houses[:c] + remaining_houses[c+1:]
                    break

            if res is None:
                for i, (l,u) in enumerate(HUMAN_DISTRIBUTION.keys()):
                    if l <= human.age < u:
                        bin = (l,u)
                        break

                house_size_preference = HUMAN_DISTRIBUTION[(l,u)]['residence_preference']['house_size']
                cap = self.rng.choice(range(1,6), p=house_size_preference, size=1)
                res = self.create_location(LOCATION_DISTRIBUTION['household'], 'household', len(self.households))
                if cap - 1 > 0:
                    remaining_houses.append((res, cap-1))

            # FIXME: there is some circular reference here
            res.residents.append(human)
            human.assign_household(res)
            self.households.add(res)

        # assign area to house
        area = _get_random_area(len(self.households), LOCATION_DISTRIBUTION['household']['area'] * self.total_area, self.rng)
        for i,house in enumerate(self.households):
            house.area = area[i]
Example #3
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