def _select_family_schema(self, human): while True: # TODO use a realistic distribution schema = random_selection(self._schema_collection) if self._is_compatible(human, schema): break return copy.deepcopy(schema)
def allocate_school_districts(self, school_districts, temperature): similarities = [] room_sizes = {} count = 0 for school_district in school_districts: included_set = set() students = set() teachers_candidates = set() for school in school_district.locations: for classroom in school.locations: if "vector" in self.unit_info_map[classroom.strid]: included_set.add( self.unit_info_map[classroom.strid]["vector"]) #school_district_distribution = copy.deepcopy(self.roulette_distribution) #self.only_keep_columns_in_set(school_district_distribution,included_set) for grid_tuple in school_district.home_district_list: home_district = self.home_district_in_position[grid_tuple] for apartment_building in home_district.locations: for apartment in apartment_building.locations: for human in apartment.allocation: if isinstance(human, K12Student): students.add(human) # No adult is assigned to be a teacher in human's factory. This method 'converts' # adult's work info to be a TEACHER. So if an adult is already set to be a teacher # it means it has already been selected as a teacher hence it can't be selected again elif isinstance( human, Adult ) and human.work_info.work_class != WorkClasses.TEACHER: teachers_candidates.add(human) #print (f"{len(students)} to be allocated into school districts") teachers_candidates = list(teachers_candidates) self.allocate_schools(included_set, students, temperature) for school in school_district.locations: for classroom in school.locations: if len(classroom.allocation) > 0: if ENABLE_WORKER_CLASS_SPECIAL_BUILDINGS: for i in range(self.teachers_per_classroom): teacher = random_selection(teachers_candidates) teacher.change_work_info_to_teacher() self.allocate_workplace( classroom.strid, teacher) if self.teachers_per_classroom > 1: teachers_candidates.remove(teacher) room_sizes[count] = len(classroom.allocation) count += 1 for student in classroom.allocation: tup_vec1 = self.unit_info_map[ classroom.strid]["vector"] tup_vec2 = self.feature_vector[student] sim = self.similarity(tup_vec1, tup_vec2) similarities.append(sim) avg_sim = mean(similarities) print( f"Average similarity between students and their classroom is {avg_sim} at temperature {temperature}" ) avg_size = mean(list(room_sizes.values())) print( f"Average classroom occupancy is {avg_size} and number classrooms is {len(room_sizes)}" )
def _select_family_schema(self, human): #first filter out compatables, then assign #else this would take longer than necessary compatable = [clist for clist in self._schema_collection if self._is_compatible(human,clist)] #compatable = [clist for clist in self._schema_collection ]#fixme schema = random_selection(compatable) # TODO use a realistic distribution return copy.deepcopy(schema)
def _select(self, building_type, n, same_unit, exclusive): count = 0 while True: count += 1 assert count < (len(self.locations) * 1000) # infinit loop building = random_selection(self.locations) if not isinstance(building, building_type): continue for unit in building.locations: if exclusive: if not unit.allocation: return (building, unit) else: vacancy = unit.capacity - len(unit.allocation) if vacancy >= n or vacancy == 1 and not same_unit: return (building, unit)
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), } self.work_info = WorkInfo() # TODO change to use some realistic distribution selected_class = random_selection([key for key in income.keys()]) 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 test_random_selection(): random_numbers = np.random.rand(5) assert base.random_selection(random_numbers, 1) in random_numbers
def select_random_coordinates(self): v = random_selection(self.all_zones_coordinates) p = random_selection(v, 2) return [(p[0][0] + p[1][0]) / 2, (p[0][1] + p[1][1]) / 2]
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 ]