def check_if_has_holes(sln: RegionMap):
    districts = sln.districts

    for dist in districts:
        neighboring_districts = sln.get_neighboring_districts_of(dist)
        if len(neighboring_districts) > 1:
            continue

        units_on_region_border = dist.get_district_units_on_region_border()
        if len(units_on_region_border) == 0:
            return True

    return False
예제 #2
0
def create_neighboring_sln(cur_sln: RegionMap):
    """Generates a neighboring solution using the Ising models approach"""

    # if unit borders several districts, choose one of these districts randomly
    # decide randomly if unit should "go" to another district
    all_units = Units.units()
    for cur_unit in all_units:
        cur_district = cur_sln.find_district_by_unit(cur_unit)

        # if cur_unit is the only unit in the district, do not change cur_unit "membership"
        # (in favor of another district)
        if len(cur_district) <= 1:
            continue

        neighboring_districts_collection = cur_sln.get_neighboring_districts_of(cur_district)

        # find those districts that cur_unit borders
        districts_that_cur_unit_borders = []
        for neighboring_district in neighboring_districts_collection:
            bordering_units = cur_district.get_units_bordering_that_district(neighboring_district)

            if cur_unit in bordering_units:
                districts_that_cur_unit_borders.append(neighboring_district)

        if len(districts_that_cur_unit_borders) == 0:
            continue

        random_district = rd.choice(districts_that_cur_unit_borders)

        cur_district.remove_unit(cur_unit)
        random_district.add_unit(cur_unit)

        # revert the move if it breaks contiguity or if the move creates holes
        if not check_if_contiguous(cur_district) or check_if_has_holes(cur_sln):
            random_district.remove_unit(cur_unit)
            cur_district.add_unit(cur_unit)

    return cur_sln