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)
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]
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