Exemplo n.º 1
0
 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
Exemplo n.º 2
0
 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
Exemplo n.º 3
0
    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
Exemplo n.º 4
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),
        }
        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
Exemplo n.º 5
0
    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
Exemplo n.º 6
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)
Exemplo n.º 7
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
                    ]