def build_tribe(self, human, humans, mininum, maximum): n = linear_rescale(human.properties.extroversion, mininum, maximum) w = [self.similarity[human][h] for h in humans] tribe = [human] count = 0 while n > 0 and count < len(humans): count += 1 selected = roulette_selection(humans, w) if selected not in tribe: tribe.append(selected) n -= 1 return tribe
def build_tribe(self, human, humans, mininum, maximum): n = int(round(linear_rescale(human.properties.extroversion, mininum, maximum))) if n >= len(humans): n = len(humans) - 1 if n <= 0: return [human] tribe_candidates = humans.copy() tribe_candidates.remove(human) w = [self.similarity[human][h] for h in tribe_candidates] tribe = roulette_selection(tribe_candidates, w, num_selections=n) tribe.append(human) return tribe
def setup_work_info(self): # Teachers are kept out of roulette because they are assigned by hand depending on the number of classrooms work_class_base_info = [ # (class, weight, income, income when in lockdown) (WorkClasses.OFFICE, 1, 1, 0), (WorkClasses.HOUSEBOUND, 1, 1, 1), (WorkClasses.FACTORY, 1, 1, 0), (WorkClasses.RETAIL, 1, 1, 0) ] if ENABLE_WORKER_CLASS_SPECIAL_BUILDINGS: work_class_base_info.append((WorkClasses.HOSPITAL, 0.1, 1, 1)) work_classes = [] work_classes_weights = [] # used to determine the number of workers of each class income = {} for work_class, income_no_lockdown, income_lockdown, weight in work_class_base_info: work_classes.append(work_class) work_classes_weights.append(weight) income[work_class] = (income_no_lockdown, income_lockdown) self.work_info = WorkInfo() # TODO change to use some realistic distribution selected_class = roulette_selection(work_classes, work_classes_weights) self.work_info.work_class = selected_class self.work_info.base_income, self.work_info.income_loss_isolated = income[selected_class] self.work_info.can_work_from_home = \ selected_class == WorkClasses.OFFICE or \ selected_class == WorkClasses.HOUSEBOUND self.work_info.meet_non_coworkers_at_work = \ selected_class == WorkClasses.RETAIL or \ selected_class == WorkClasses.HOSPITAL self.work_info.essential_worker = \ selected_class == WorkClasses.HOSPITAL self.work_info.fixed_work_location = \ selected_class == WorkClasses.OFFICE or \ selected_class == WorkClasses.HOUSEBOUND or \ selected_class == WorkClasses.FACTORY or \ selected_class == WorkClasses.RETAIL or \ selected_class == WorkClasses.HOSPITAL self.work_info.house_bound_worker = selected_class == WorkClasses.HOUSEBOUND
def setup_work_info(self): income = { # Income (in [0..1]) when the people is working and when he/she is isolated at home WorkClasses.OFFICE: (1.0, 0.0), WorkClasses.HOUSEBOUND: (1.0, 0.0), WorkClasses.FACTORY: (1.0, 1.0), WorkClasses.RETAIL: (1.0, 1.0), WorkClasses.ESSENTIAL: (1.0, 1.0), } classes = [key for key in income.keys()] roulette = [] self.work_info = WorkInfo() #TODO change to use some realistic distribution count = 1 for wclass in classes: roulette.append(count / len(classes)) count = count + 1 selected_class = roulette_selection(classes, roulette) self.work_info.work_class = selected_class self.work_info.base_income, self.work_info.income_loss_isolated = income[selected_class] self.work_info.can_work_from_home = \ selected_class == WorkClasses.OFFICE or \ selected_class == WorkClasses.HOUSEBOUND self.work_info.meet_non_coworkers_at_work = \ selected_class == WorkClasses.RETAIL or \ selected_class == WorkClasses.ESSENTIAL self.work_info.essential_worker = \ selected_class == WorkClasses.ESSENTIAL self.work_info.fixed_work_location = \ selected_class == WorkClasses.OFFICE or \ selected_class == WorkClasses.HOUSEBOUND or \ selected_class == WorkClasses.FACTORY or \ selected_class == WorkClasses.RETAIL or \ selected_class == WorkClasses.ESSENTIAL self.work_info.house_bound_worker = WorkClasses.HOUSEBOUND
def setup_work_info(self): classes = [ WorkClasses.OFFICE, WorkClasses.HOUSEBOND, WorkClasses.FACTORY, WorkClasses.RETAIL, WorkClasses.ESSENTIAL, WorkClasses.TRANSPORTATION ] roulette = [] count = 1 #TODO change to use some realistic distribution for wclass in classes: roulette.append(count / len(classes)) count = count + 1 selected_class = roulette_selection(classes, roulette) self.work_info = WorkInfo() self.work_info.can_work_from_home = \ selected_class == WorkClasses.OFFICE or \ selected_class == WorkClasses.HOUSEBOND self.work_info.meet_non_coworkers_at_work = \ selected_class == WorkClasses.RETAIL or \ selected_class == WorkClasses.ESSENTIAL or \ selected_class == WorkClasses.TRANSPORTATION self.work_info.essential_worker = WorkClasses.ESSENTIAL self.work_info.fixed_work_location = \ selected_class == WorkClasses.OFFICE or \ selected_class == WorkClasses.HOUSEBOND or \ selected_class == WorkClasses.FACTORY or \ selected_class == WorkClasses.RETAIL or \ selected_class == WorkClasses.ESSENTIAL self.work_info.house_bound_worker = WorkClasses.HOUSEBOND self.work_info.earnings = 0.0
def _select_family_schema(self, human): while True: schema = roulette_selection(self._schema_collection, self._weights) if self._is_compatible(human, schema): break return copy.deepcopy(schema)
def __init__(self, city, population_size, model): self.work_zones = [ 'GM', 'IC', 'GR', 'CS', 'HC', 'O-1', 'O-2', 'LI', 'HM', 'GI', 'LB', 'WC-1', 'WC-2', 'WC-3', 'RI', 'CC', 'COM-1', 'COM-2', 'CNTY-A-1', 'CNTY-M-1', 'CNTY-C-2' ] self.home_zones = [ 'R-SF', 'R-LD', 'R-TH', 'R-MD', 'CNTY-R-1', 'R-MHC', 'R-HD' ] self.unused_zones = ['PD', 'CNTY-PAD', None] home_low_density_capacity = 20 home_medium_density_capacity = 150 home_high_density_capacity = 450 family_capacity_per_building = { 'R-SF': 1, 'R-LD': home_low_density_capacity, 'R-TH': home_low_density_capacity, 'R-MD': home_medium_density_capacity, 'CNTY-R-1': home_medium_density_capacity, 'R-MHC': home_medium_density_capacity, 'R-HD': home_high_density_capacity } family_capacity = {} self.model = model self.population_size = population_size self.zone_centroid = {} self.work_building_ids = [] self.home_building_ids = [] self.school_building_ids = [] self.restaurant_building_ids = [] self.home_building = {} self.work_building = {} self.school_building = {} self.restaurant_building = {} self.restaurant_distances = {} self.school_distances = {} self.work_zone_distances = {} self.restaurant_roulette = {} self.school_roulette = {} self.work_zone_roulette = {} self.sigma = get_parameters( ).params['real_sites_roulette_rescale_sigma'] self.kappa = get_parameters( ).params['real_sites_roulette_rescale_kappa'] home_district = District('HomeDistrict', model, '', '') work_district = District('WorkDistrict', model, '', '') school_district = District('SchoolDistrict', model, '', '') restaurant_district = District('RestaurantDistrict', model, '', '') with open(f'mesa-geo/examples/GeoSIR/{city}/neighborhoods.geojson' ) as json_file: self.neighborhoods = json.load(json_file) self.neighborhoods_count = len(self.neighborhoods['features']) print( f"Total number of neighboorhoods: {self.neighborhoods_count}") with open(f'mesa-geo/examples/GeoSIR/{city}/schools.geojson' ) as json_file: self.schools = json.load(json_file) self.schools_count = len(self.schools['features']) for school in self.schools['features']: bid = str(school['properties']['OBJECTID']) self.school_building_ids.append(bid) self.school_building[bid] = HomogeneousBuilding( 1000000, model, 'School', bid) school_district.locations.append(self.school_building[bid]) print(f"Total number of schools: {self.schools_count}") with open(f'mesa-geo/examples/GeoSIR/{city}/zoning.geojson' ) as json_file: self.buildings = json.load(json_file) print( f"Total number of buildings: {len(self.buildings['features'])}" ) self.all_zones_coordinates = [] for building in self.buildings['features']: bid = str(building['properties']['OBJECTID']) self.zone_centroid[bid] = self.compute_centroid(building) zone = building['properties']['PLANZONE'] if building['geometry']['type'] == 'Polygon': self.all_zones_coordinates.append( building['geometry']['coordinates'][0]) elif building['geometry']['type'] == 'MultiPolygon': for v in building['geometry']['coordinates']: self.all_zones_coordinates.append(v[0]) else: assert False if zone in self.work_zones: self.work_building_ids.append(bid) self.work_building[bid] = HomogeneousBuilding( 1000000, model, 'Work', bid) work_district.locations.append(self.work_building[bid]) elif zone in self.home_zones: family_capacity[bid] = family_capacity_per_building[zone] self.home_building_ids.append(bid) self.home_building[bid] = HomogeneousBuilding( family_capacity[bid], model, 'Home', bid) home_district.locations.append(self.home_building[bid]) elif zone not in self.unused_zones: print(f"Unknown zone type: {zone}") exit() self.restaurants = self.create_geo_restaurants(self.buildings) self.restaurants_count = len(self.restaurants['features']) for restaurant in self.restaurants['features']: bid_int = restaurant['properties']['OBJECTID'] bid = str(bid_int) self.restaurant_building_ids.append(bid) self.restaurant_building[bid] = self.create_restaurant_location( bid_int, flip_coin(0.1)) restaurant_district.locations.append(self.restaurant_building[bid]) print(f"Total number of restaurants: {self.restaurants_count}") with open('restaurants.geojson', 'w') as fp: json.dump(self.restaurants, fp) distance_cache_file = f'mesa-geo/examples/GeoSIR/{city}/distances_{self.sigma}_{self.kappa}.json' if os.path.isfile(distance_cache_file): with open(distance_cache_file) as json_file: table = json.load(json_file) self.restaurant_distances = table['restaurant_distances'] self.school_distances = table['school_distances'] self.work_zone_distances = table['work_zone_distances'] self.restaurant_roulette = table['restaurant_roulette'] self.school_roulette = table['school_roulette'] self.work_zone_roulette = table['work_zone_roulette'] else: self.compute_restaurant_distances() self.compute_school_distances() self.compute_work_zone_distances() table = {} table['restaurant_distances'] = self.restaurant_distances table['school_distances'] = self.school_distances table['work_zone_distances'] = self.work_zone_distances table['restaurant_roulette'] = self.restaurant_roulette table['school_roulette'] = self.school_roulette table['work_zone_roulette'] = self.work_zone_roulette with open(distance_cache_file, 'w') as json_file: json.dump(table, json_file) family_factory = FamilyFactory(model) family_factory.factory(population_size) model.global_count.total_population = family_factory.human_count print(f"Total number of families: {len(family_factory.families)}") #count_family = 0 for family in family_factory.families: #if count_family % 1000 == 0: print(f"{count_family} {datetime.datetime.now()}") #count_family += 1 assert len(self.home_building_ids) > 0 home_bid = random_selection(self.home_building_ids) selected_home_build = self.home_building[home_bid] home_unit = BuildingUnit(10, model, home_bid, '', contagion_probability=beta_range( 0.021, 0.12)) family_capacity[home_bid] -= 1 if family_capacity[home_bid] == 0: self.home_building_ids.remove(home_bid) selected_home_build.locations.append(home_unit) for human in family: # Home human.home_district = home_district home_district.allocation[human] = [selected_home_build] home_unit.allocation.append(human) selected_home_build.allocation[human] = home_unit assert home_district.get_buildings(human)[0].get_unit( human) == home_unit home_unit.humans.append(human) # Work if isinstance(human, Adult): human.work_district = work_district #work_bid = random_selection(self.work_building_ids) work_bid = roulette_selection( self.work_zone_distances[home_bid]['work_zone_bid'], self.work_zone_distances[home_bid]['distance'], roulette=self.work_zone_roulette[home_bid]) selected_work_building = self.work_building[work_bid] work_unit = selected_work_building.locations[-1] if selected_work_building.locations and\ len(work_unit.allocation) < work_unit.capacity else None if work_unit is None: work_unit = BuildingUnit( 10, model, work_bid, '', contagion_probability=beta_range(0.007, 0.06)) selected_work_building.locations.append(work_unit) work_district.allocation[human] = [selected_work_building] work_unit.allocation.append(human) selected_work_building.allocation[human] = work_unit assert work_district.get_buildings(human)[0].get_unit( human) == work_unit # School if isinstance(human, K12Student): human.school_district = school_district #work_bid = random_selection(self.school_building_ids) school_bid = roulette_selection( self.school_distances[home_bid]['school_bid'], self.school_distances[home_bid]['distance'], roulette=self.school_roulette[home_bid]) selected_school_building = self.school_building[school_bid] school_unit = selected_school_building.locations[-1] if selected_school_building.locations and\ len(school_unit.allocation) < school_unit.capacity else None if school_unit is None: school_unit = BuildingUnit( 20, model, school_bid, '', contagion_probability=beta_range(0.014, 0.08)) selected_school_building.locations.append(school_unit) school_district.allocation[human] = [ selected_school_building ] school_unit.allocation.append(human) selected_school_building.allocation[human] = school_unit assert school_district.get_buildings(human)[0].get_unit( human) == school_unit # Restaurants if isinstance(human, Adult): #bids = [random_selection(self.restaurant_building_ids) for i in range(10)] bids = roulette_selection( self.restaurant_distances[work_bid]['restaurant_bid'], self.restaurant_distances[work_bid]['distance'], 10, roulette=self.restaurant_roulette[work_bid]) human.preferred_restaurants = [ self.restaurant_building[bid] for bid in bids ]