Example #1
0
def link_public_private_buildings(building_data):
    for resd_building in bt.find_buildings_in_type(bt.RESIDENTIAL,
                                                   building_data):
        for type in bt.ALL_PUBLIC_BUILDING_TYPES:
            public_buildings_in_type = bt.find_buildings_in_type(
                type, building_data)

            dist_lst = [
                (public_in_type,
                 util.calc_distance_two_buildings(resd_building,
                                                  public_in_type))
                for public_in_type in public_buildings_in_type
            ]
            dist_lst_sorted = sorted(dist_lst, key=lambda x: x[1])
            # closest public, take the first argument of the tuple (building, dist)

            # closest_public = dist_lst_sorted[0]
            closest_public = dist_lst_sorted[0][0]
            dist = dist_lst_sorted[0][1]

            # link residential to public
            closest_public.add_user_buildings(resd_building)
            # link public to residential
            resd_building.add_used_public_building(closest_public, dist)

    return building_data
Example #2
0
    def __evaluate_plan_distance(self):
        # if already calculated:
        if self.__plan_distance_score != -1:
            return self.__plan_distance_score

        # first time, should calculate it
        self.__plan_distance_score = 1
        # loop over only public buildings!!
        for b_type in bt.ALL_PUBLIC_BUILDING_TYPES:
            buildings_in_type = bt.find_buildings_in_type(b_type, self.updated_building_data_all)
            updated_building_data_resd = bt.find_buildings_in_type(bt.RESIDENTIAL, self.updated_building_data_all)
            sum_avg_dist_lst_prob = evaluate_buildings_distances_for_type(updated_building_data_resd, buildings_in_type)

            # finally, duplicate the probability (importance) of the PUBLIC buildings with its extra height
            i = 0
            evaluated_for_type = 0.0
            sum_all_public_same_type = 0.0
            for public_building in buildings_in_type:
                sum_area_public_building = public_building.get_extra_height() * public_building.get_area()
                sum_all_public_same_type += sum_area_public_building
                evaluated_for_type += sum_avg_dist_lst_prob[i] * (sum_area_public_building)

                # take sum_avg_dist_lst_prob[i] * sum_area_public_building as output maybe
                # so it will be good both for evalation and both calc_public_floors...
            if evaluated_for_type > 0:
                self.__plan_distance_score *= evaluated_for_type/max(sum_all_public_same_type, 1)

        return self.__plan_distance_score
Example #3
0
    def __evaluate_plan_linked_distance(self):
        if self.__plan_distance_score != -1:
            return self.__plan_distance_score

        # first time, should calculate it
        self.__plan_distance_score = 1
        # loop over only public buildings!!
        for b_type in bt.ALL_PUBLIC_BUILDING_TYPES:
            buildings_in_type = bt.find_buildings_in_type(b_type, self.updated_building_data_all)
            updated_building_data_resd = bt.find_buildings_in_type(bt.RESIDENTIAL, self.updated_building_data_all)
            updated_building_data_public_type = bt.find_buildings_in_type(b_type, self.updated_building_data_all)
            for p_building in updated_building_data_public_type:
                for building_resd_used in p_building.get_users_buildings():
                    pass
Example #4
0
    def __calculate_public_plan_prob_importance(self):
        # in current situation (before building more floors), we don't know the cost, because it depends on the num
        # of floors, and the needs are mandatory for us. so importance is based on distance only.
        public_plan_prob_vec_per_type_dist = dict()

        # same function used for evaluation (distance parameter), just for planning the public here.
        for public_type in bt.all_public_building_types():
            # it doesnt' matter if it is self.__init_buildings_data or updated_building_data_resd,
            # because the public buildings are not updated anyway..
            public_buildings_sametype = bt.find_buildings_in_type(public_type, self.__init_buildings_data)
            updated_building_data_resd = bt.find_buildings_in_type(bt.RESIDENTIAL, self.updated_building_data_all)
            public_plan_prob_vec_per_type_dist[public_type] = evaluate_buildings_distances_for_type\
                (updated_building_data_resd, public_buildings_sametype)

        return public_plan_prob_vec_per_type_dist
def evaluate_personal_satisfaction(plan):

    residential_buildings = bt.find_buildings_in_type(bt.RESIDENTIAL, plan)

    people = []
    people.append(p.Person(CHILD, False))
    people.append(p.Person(SINGLE, False))
    people.append(p.Person(SINGLE, True))
    people.append(p.Person(PARENT, False))
    people.append(p.Person(ELDERLY, True))
    personal_satisfaction_raw = []
    max_sat = 0
    for person in people:
        curr_person_type_score = []
        for j in range(50):
            person.set_residence(residential_buildings[np.random.randint(
                len(residential_buildings))])
            # curr_sat = round(person.set_satisfaction(),4)
            curr_sat = person.set_satisfaction()
            curr_person_type_score.append(curr_sat)
        curr_person_type_sat = np.mean(curr_person_type_score)
        personal_satisfaction_raw.append(curr_person_type_sat)

        if (curr_person_type_sat > max_sat):
            max_sat = curr_person_type_sat

    personal_satisfaction = []
    for i in range(len(people)):
        curr_sat = round(personal_satisfaction_raw[i] / max_sat, 4)
        personal_satisfaction.append(
            (people[i].get_type(), str(people[i].get_religious()),
             people[i].get_residence(), curr_sat))
    return personal_satisfaction
Example #6
0
    def __calculate_public_plan(self):
        for public_type in bt.ALL_PUBLIC_BUILDING_TYPES:
            units_needed_for_type = self.__all_needs[public_type]  # ex: 3 units
            area_per_unit_for_type = needs.one_unit_in_meter_square(public_type)  # ex: 100 m^2 per unit
            area_needed_for_type = units_needed_for_type * area_per_unit_for_type  # ex: 300 m^2 overall
            public_in_type = bt.find_buildings_in_type(public_type, self.updated_building_data_all)
            left_area = area_needed_for_type
            idx = 0
            search_more = True
            while left_area > 0 and search_more:
                building_score_type = [(public_building.calc_building_score(self.__all_needs), public_building)
                                       for public_building in public_in_type]

                building_score_type_sorted = sorted(building_score_type, key=lambda x: x[0])
                # take the building with the lowest score
                while idx < len(building_score_type_sorted):
                    first_to_build = building_score_type_sorted[idx][1]
                    building_area = first_to_build.get_area()
                    building_height = first_to_build.get_overall_height()
                    max_height = first_to_build.get_max_height()
                    if (building_height > max_height):
                        idx += 1
                        if idx == len(building_score_type_sorted):
                            search_more = False
                    elif left_area > 0.5 * building_area:
                        # if worth to add a floor
                        first_to_build.add_extra_height(1)
                        left_area -= building_area
                        break
                    else:
                        idx += 1
                        if idx == len(building_score_type_sorted):
                            search_more = False
Example #7
0
    def __evaluate_plan_needs(self):
        # already calculated:
        if self.__plan_needs_score != -1:
            return self.__plan_needs_score

        # first time, should calculate it
        self.__plan_needs_score = 1
        # for all buildings, including residential and public!!
        for b_type in bt.ALL_BUILDING_TYPES:
            unit_needs_for_type = self.__all_needs[b_type]


            buildings_in_type = bt.find_buildings_in_type(b_type, self.updated_building_data_all)
            extra_units_for_type = 0
            for building in buildings_in_type:
                extra_units_for_type += building.get_area() * building.get_extra_height()

            extra_units_for_type = math.ceil(extra_units_for_type/needs.one_unit_in_meter_square(b_type))
            ratio = 1
            if extra_units_for_type != 0 and unit_needs_for_type != 0:
                if extra_units_for_type >= unit_needs_for_type:
                    ratio = unit_needs_for_type / extra_units_for_type
                else:
                    ratio = extra_units_for_type / unit_needs_for_type

            self.__plan_needs_score *= ratio

        return self.__plan_needs_score
Example #8
0
    def get_only_floor_lst(self):
        only_floors = []
        self.updated_building_data = self.evaluate_plan_obj.get_updated_building_data_all()
        for b_type in bt.ALL_BUILDING_TYPES:
            for building in bt.find_buildings_in_type(b_type, self.updated_building_data):
                only_floors.append(building.get_extra_height())

        return only_floors
def min_conflict_solution(buildings_data, all_needs, housing_units_to_add):

    # main idea of min-conflict algorithm: in each iteration, check the conflicts, and add a floor to the
    # building with least conflict. (I think that the right way to do it is to check violations of the
    # optimal values (for example - 20 kids in a classroom, where each additional child is a conflict)
    num_added_units = 0

    added_floors_resd = [0] * len(
        bt.find_buildings_in_type(bt.RESIDENTIAL, buildings_data))
    new_state = state.State(buildings_data, added_floors_resd, all_needs)
    residential_buildings = building_types.find_buildings_in_type(
        building_types.RESIDENTIAL, buildings_data)

    # the algorithm runs until we have enough housing units
    while num_added_units < housing_units_to_add:

        # a for loop, iterating over all the residential buildings and counts their conflicts

        for i in range(10):
            if num_added_units < housing_units_to_add:
                conflicts = []
                # for building in residential_buildings:
                for i in range(len(residential_buildings)):
                    conflicts.append(
                        (calculate_conflicts(residential_buildings[i],
                                             new_state), i))

                sorted_conflicts = sorted(conflicts,
                                          key=lambda building: building[0]
                                          )  #TODO check if it works properly
                for i in range(5):
                    if num_added_units < housing_units_to_add:
                        building_to_increase = sorted_conflicts[i][1]
                        added_floors_resd[building_to_increase] += (10 - i)
                        num_added_units += util.add_floors(
                            (10 - i), new_state,
                            residential_buildings[building_to_increase]
                        )  # returns the number of units added

        new_state.update_floors(added_floors_resd)

    # score
    return (new_state.get_score(), new_state.get_updated_building_data())
Example #10
0
 def get_floor_state(self):
     if not self.additional_floors_all:
         self.updated_building_data = self.evaluate_plan_obj.get_updated_building_data_all()
         for b_type in bt.ALL_BUILDING_TYPES:
             if b_type != bt.RESIDENTIAL:
                 additional_floors_for_type = [building.get_extra_height()
                                   for building in bt.find_buildings_in_type(b_type, self.updated_building_data)]
                 self.additional_floors_all.append((b_type, additional_floors_for_type))
             else:
                 self.additional_floors_all.append((bt.RESIDENTIAL, self.additional_floors_resd))
     return self.additional_floors_all
def reproduce(population, buildings_data, add_housing_unit, all_needs,
              mutatio_prob):
    residential_buildings = bt.find_buildings_in_type(bt.RESIDENTIAL,
                                                      buildings_data)
    elite = get_top_individuals(population)
    new_pop = elite
    while (len(new_pop) < len(population) * 4):
        random_val = random.random()
        if (random_val < mutatio_prob):
            new_individual = generate_random_state(buildings_data,
                                                   add_housing_unit, all_needs)
        else:
            new_individual = merge_elite(get_pair(elite), add_housing_unit,
                                         all_needs, residential_buildings)
        new_pop.append(new_individual)
    new_pop = get_top_individuals(new_pop)
    return new_pop
def generate_random_state(buildings_data, add_housing_units, all_needs_dict):

    residential_buildings = bt.find_buildings_in_type(bt.RESIDENTIAL,
                                                      buildings_data)

    added_floors_resd = [0] * len(residential_buildings)
    units_added = 0

    while units_added < add_housing_units:
        building_to_rise = random.randint(0, len(residential_buildings) - 1)
        added_floors_resd[building_to_rise] += 1
        units_added += util.get_units_added_to_one_building(
            residential_buildings[building_to_rise], 1)

    new_state = state.State(buildings_data, added_floors_resd, all_needs_dict)

    return new_state
Example #13
0
    def __init__(self, init_buildings_data, plan_floors_resd_state, all_needs):
        self.__init_buildings_data = init_buildings_data
        self.__init_buildings_data_resd = bt.find_buildings_in_type(bt.RESIDENTIAL, init_buildings_data)
        self.__buildings_data_public = bt.find_buildings_public(init_buildings_data)
        self.__plan_floors_resd_state = plan_floors_resd_state
        self.__all_needs = all_needs

        # this function is updating the the init_building_data with the new state of additional floors
        # of ONLY residential buildings. the result will be stores in __updated_building_data_resd
        self.updated_building_data_all = \
            bt.update_building_resd_with_floors_plan(self.__init_buildings_data, plan_floors_resd_state)
        self.__plan_needs_score = -1
        self.__plan_distance_score = -1
        self.__plan_cost_score = -1

        # CALCULATE PUBLIC PLAN, and update retult in __init_building_data
        # like __init_building_data, updated with extra floors of the given RESIDENTIAL (state), and the calculated PUBLIC
        self.__calculate_public_plan()
Example #14
0
    def __evaluate_plan_cost(self):
        # already calculated:
        if self.__plan_cost_score != -1:
            return self.__plan_cost_score

        self.__plan_cost_score = 1
        for b_type in bt.ALL_BUILDING_TYPES :
            for building in bt.find_buildings_in_type(b_type, self.updated_building_data_all):
                original_height = building.get_init_height()
                extra_height = building.get_extra_height()
                extra_extra = max(extra_height - math.ceil(FLOORS_PRCTG * original_height), 0)
                cost = pow(COST_MORE_PRSTG, extra_extra)
                if extra_height >= FLOORS_NUM:
                    cost = min(COST_MORE_NUM_FLOORS, 1-cost)

                self.__plan_cost_score *= cost  # max(evaluated_for_type / needs_for_type, 1)

        return self.__plan_cost_score
Example #15
0
def calc_needs(buildings_data, add_housing_units):

    add_population = math.ceil(add_housing_units * AVG_FAMILY_SIZE)
    original_population = math.ceil(
        get_residential_sum_area(buildings_data) / METERS_PER_UNIT *
        AVG_FAMILY_SIZE)

    type_importance_dict = {}
    avg_imp = 1 / (len(bt.ALL_BUILDING_TYPES) - 1
                   )  # -1 for not considering the residential
    for building in bt.ALL_BUILDING_TYPES:
        type_importance_dict[str(building)] = avg_imp

    # number of kids in a certain age (for ex. 102 kids in the age of 10 yo)
    # grade_size = age_percentage18 * population_increase / PERCENTAGE
    grade_size = AGE_GROUP18_PRCTG * add_population / PERCENTAGE

    # add units of public services
    kindergarden_needs = (grade_size * KINDERGARDEN_NUM_GRADES) / CLASS_SIZE
    primary_needs = (grade_size * PRIMARY_NUM_GRADES) / CLASS_SIZE
    highschool_needs = (grade_size * HS_NUM_GRADES) / CLASS_SIZE

    synagogue_needs = math.ceil(
        ((add_population * RELIGION_PRCTG / PERCENTAGE) * 0.49) *
        1.1) / one_unit_in_meter_square(bt.SYNAGOUGE)
    mikve_needs = math.ceil(
        ((add_population * RELIGION_PRCTG / PERCENTAGE) / 22.5) *
        0.35) / one_unit_in_meter_square(bt.MIKVE)  # 0.35 instead of 0.007

    # POLICE
    previous_police = 0
    for building in bt.find_buildings_in_type(bt.POLICE, buildings_data):
        previous_police += building.get_area()

    if add_population + original_population < 7000:
        police_needs = max(100 - previous_police, 0)
    elif add_population + original_population < 15000:
        police_needs = max(500 - previous_police, 0)
    elif add_population + original_population < 40000:
        police_needs = max(1500 - previous_police, 0)
    elif add_population + original_population < 100000:
        police_needs = max(3600 - previous_police, 0)
    else:
        police_needs = max(4400 - previous_police, 0)
    police_needs /= math.ceil(one_unit_in_meter_square(bt.POLICE))

    # COMMUNITY CENTER
    previous_community = 0
    for building in bt.find_buildings_in_type(bt.COMMUNITY_CNTR,
                                              buildings_data):
        previous_community += building.get_area()
    if add_population + original_population < 300:
        community_center_needs = max(250 - previous_community, 0)
    elif add_population + original_population < 600:
        community_center_needs = max(400 - previous_community, 0)
    else:
        community_center_needs = max(750 - previous_community, 0)
    community_center_needs /= one_unit_in_meter_square(bt.COMMUNITY_CNTR)

    # ELDERLY CENTER
    elderly_center_needs = 0

    # CLINIC
    previous_health_clinic = 0
    for building in bt.find_buildings_in_type(bt.CLINIC, buildings_data):
        previous_health_clinic += building.get_area()

    if add_population + original_population < 300:
        health_clinic_needs = max(300 - previous_health_clinic, 0)
    elif add_population + original_population < 600:
        health_clinic_needs = max(500 - previous_health_clinic, 0)
    else:
        health_clinic_needs = max(1000 - previous_health_clinic, 0)
    health_clinic_needs /= one_unit_in_meter_square(bt.CLINIC)

    # HOSPITAL
    hospital_needs = 0

    # SPORT
    sport_needs = 0

    all_needs_dict = dict()
    # All needs are in area (square meters)
    for b_type in bt.ALL_BUILDING_TYPES:
        if b_type == bt.KINDERGARDEN:
            all_needs_dict[b_type] = kindergarden_needs
        elif b_type == bt.PRIMARY_SCHOOL:
            all_needs_dict[b_type] = primary_needs
        elif b_type == bt.HIGH_SCHOOL:
            all_needs_dict[b_type] = highschool_needs
        elif b_type == bt.SYNAGOUGE:
            all_needs_dict[b_type] = synagogue_needs
        elif b_type == bt.MIKVE:
            all_needs_dict[b_type] = mikve_needs
        elif b_type == bt.POLICE:
            all_needs_dict[b_type] = police_needs
        elif b_type == bt.COMMUNITY_CNTR:
            all_needs_dict[b_type] = community_center_needs
        elif b_type == bt.ELDERLY_CNTR:
            all_needs_dict[b_type] = elderly_center_needs
        elif b_type == bt.CLINIC:
            all_needs_dict[b_type] = health_clinic_needs
        elif b_type == bt.HOSPITAL:
            all_needs_dict[b_type] = hospital_needs
        elif b_type == bt.SPORT:
            all_needs_dict[b_type] = sport_needs
        elif b_type == bt.RESIDENTIAL:
            all_needs_dict[b_type] = add_housing_units
    return all_needs_dict
Example #16
0
def get_residential_sum_area(building_data):
    resd_buildings = bt.find_buildings_in_type(bt.RESIDENTIAL, building_data)
    all_areas = [resd_building.get_area() for resd_building in resd_buildings]
    return sum(all_areas)