Exemple #1
0
 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)
Exemple #5
0
    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
Exemple #6
0
def test_random_selection():
    random_numbers = np.random.rand(5)
    assert base.random_selection(random_numbers, 1) in random_numbers
Exemple #7
0
 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]
Exemple #8
0
    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
                    ]