Example #1
0
def getpart(i):
    humanlist = ['judge', 'oldplan', 'newplan']
    if i < 3:
        ass = Partition(graph, humanlist[i], my_updaters).assignment
        to0index = {x: i for i, x in enumerate(ass.parts)}
        return Partition(graph, {n: to0index[ass[n]]
                                 for n in graph.nodes}, my_updaters)
    else:
        ass = get_partition(files[240 * (i)], fid_to_geoid_file, geoidcol)
        return Partition(graph, ass, my_updaters)
Example #2
0
    def test_uses_graph_geometries_by_default(self, geodataframe):
        mock_plot = MagicMock()
        gp.GeoDataFrame.plot = mock_plot

        graph = Graph.from_geodataframe(geodataframe)
        partition = Partition(graph=graph,
                              assignment={node: 0
                                          for node in graph})
        partition.plot()
        assert mock_plot.call_count == 1
Example #3
0
def test_data_tally_works_as_an_updater(three_by_three_grid):
    assignment = random_assignment(three_by_three_grid, 4)
    data = {node: random.randint(1, 100) for node in three_by_three_grid.nodes}
    parts = tuple(set(assignment.values()))
    updaters = {"tally": DataTally(data, alias="tally")}
    partition = Partition(three_by_three_grid, assignment, updaters)

    flip = {random.choice(list(partition.graph.nodes)): random.choice(parts)}
    new_partition = partition.flip(flip)

    assert new_partition["tally"]
Example #4
0
def test_data_tally_gives_expected_value(three_by_three_grid):
    first_node = next(iter(three_by_three_grid.nodes))
    assignment = {node: 1 for node in three_by_three_grid.nodes}
    assignment[first_node] = 2

    data = {node: 1 for node in three_by_three_grid}
    updaters = {"tally": DataTally(data, alias="tally")}
    partition = Partition(three_by_three_grid, assignment, updaters)

    flip = {first_node: 1}
    new_partition = partition.flip(flip)

    assert new_partition["tally"][1] == partition["tally"][1] + 1
Example #5
0
def test_implementation_of_cut_edges_matches_naive_method(three_by_three_grid):
    graph = three_by_three_grid
    assignment = {0: 1, 1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2}
    partition = Partition(graph, assignment, {"cut_edges": cut_edges})

    flip = {4: 2}
    new_partition = Partition(parent=partition, flips=flip)
    result = cut_edges(new_partition)

    naive_cut_edges = {
        edge
        for edge in graph.edges if new_partition.crosses_parts(edge)
    }

    assert edge_set_equal(result, naive_cut_edges)
Example #6
0
def split_partition(graph_with_counties):
    partition = Partition(
        graph_with_counties,
        assignment={
            0: 1,
            1: 2,
            2: 3,
            3: 1,
            4: 2,
            5: 3,
            6: 1,
            7: 2,
            8: 3
        },
        updaters={
            "cut_edges":
            cut_edges,
            "splits":
            LocalitySplits("splittings", "county", "pop", [
                'num_parts', 'num_pieces', 'naked_boundary', 'shannon_entropy',
                'power_entropy', 'symmetric_entropy', 'num_split_localities'
            ])
        },
    )
    return partition
Example #7
0
    def test_no_splits(self, graph_with_counties):
        partition = Partition(graph_with_counties, assignment="county")

        result = compute_county_splits(partition, "county", None)

        for splits_info in result.values():
            assert splits_info.split == CountySplit.NOT_SPLIT
Example #8
0
def split_partition(graph_with_counties):
    partition = Partition(
        graph_with_counties,
        assignment={0: 1, 1: 1, 2: 1, 3: 1, 4: 2, 5: 2, 6: 3, 7: 3, 8: 3},
        updaters={"splits": county_splits("splits", "county")},
    )
    return partition
def buildPartition(graph, mean):
    """
    The function build 2 partition based on x coordinate value
    Parameters:
        graph (Graph): The given graph represent state information
        mean (int): the value to determine partition
    Returns:
        Partition: the partitions of the graph based on mean value
    """
    assignment = {}

    # assign node into different partition based on x coordinate
    for x in graph.node():
        if graph.node[x]['C_X'] < mean:
            assignment[x] = -1
        else:
            assignment[x] = 1

    updaters = {
        'population': Tally('population'),
        "boundary": bnodes_p,
        'cut_edges': cut_edges,
        'step_num': step_num,
        'b_nodes': b_nodes_bi,
        'base': new_base,
        'geom': geom_wait,
    }

    grid_partition = Partition(graph, assignment=assignment, updaters=updaters)
    return grid_partition
Example #10
0
def test_cut_edges_doesnt_duplicate_edges_with_different_order_of_nodes(
        three_by_three_grid):
    graph = three_by_three_grid
    assignment = {0: 1, 1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2}
    partition = Partition(graph, assignment, {"cut_edges": cut_edges})
    # 112    111
    # 112 -> 121
    # 222    222
    flip = {4: 2, 2: 1, 5: 1}

    new_partition = Partition(parent=partition, flips=flip)

    result = new_partition["cut_edges"]

    for edge in result:
        assert (edge[1], edge[0]) not in result
Example #11
0
def test_from_file_and_then_to_json_with_Partition(shapefile, target_file):
    partition = Partition.from_file(shapefile, assignment="data")

    # Even the geometry column is copied to the graph
    assert all("geometry" in node_data for node_data in partition.graph.nodes.values())

    partition.to_json(target_file)
def run_simple2(graph):
    election = Election("2014 Senate", {
        "Democratic": "sen_blue",
        "Republican": "sen_red"
    },
                        alias="2014_Senate")

    initial_partition = Partition(graph,
                                  assignment="con_distri",
                                  updaters={
                                      "2014_Senate":
                                      election,
                                      "population":
                                      Tally("population", alias="population"),
                                      "exterior_boundaries":
                                      exterior_boundaries,
                                      "interior_boundaries":
                                      interior_boundaries,
                                      "perimeter":
                                      perimeter,
                                      "boundary_nodes":
                                      boundary_nodes,
                                      "cut_edges":
                                      cut_edges,
                                      "area":
                                      Tally("area", alias="area"),
                                      "cut_edges_by_part":
                                      cut_edges_by_part,
                                      "county_split":
                                      county_splits('county_split',
                                                    "COUNTY_ID"),
                                      "black_population":
                                      Tally("black_pop",
                                            alias="black_population"),
                                  })
    districts_within_tolerance_2 = lambda part: districts_within_tolerance(
        part, 'population', 0.3)
    is_valid = Validator(
        [single_flip_contiguous, districts_within_tolerance_2])

    chain = MarkovChain(
        proposal=propose_random_flip,
        is_valid=is_valid,
        accept=always_accept,
        #     accept=accept, #THe acceptance criteria is what needs to be defined ourselves - to match the paper
        initial_state=initial_partition,
        total_steps=30,
    )
    efficiency_gaps = []
    wins = []

    for partition in chain:
        if (hasattr(partition, 'accepted') and partition.accepted):
            efficiency_gaps.append(
                gerrychain.scores.efficiency_gap(partition["2014_Senate"]))
            wins.append(partition["2014_Senate"].wins("Democratic"))

    return (efficiency_gaps, wins, partition)
Example #13
0
def partition(graph):
    return Partition(
        graph,
        {0: 1, 1: 1, 2: 1, 3: 2, 4: 2, 5: 2, 6: 3, 7: 3, 8: 3},
        {
            "cut_edges": updaters.cut_edges,
            "cut_edges_by_part": updaters.cut_edges_by_part,
        },
    )
Example #14
0
def test_cut_edges_by_part_doesnt_duplicate_edges_with_opposite_order_of_nodes(
        three_by_three_grid):
    graph = three_by_three_grid
    assignment = {0: 1, 1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2}
    updaters = {"cut_edges_by_part": cut_edges_by_part}
    partition = Partition(graph, assignment, updaters)
    # 112    111
    # 112 -> 121
    # 222    222
    flip = {4: 2, 2: 1, 5: 1}

    new_partition = Partition(parent=partition, flips=flip)

    result = new_partition["cut_edges_by_part"]

    for part in result:
        for edge in result[part]:
            assert (edge[1], edge[0]) not in result
Example #15
0
def test_cut_edges_can_handle_multiple_flips(three_by_three_grid):
    graph = three_by_three_grid
    assignment = {0: 1, 1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2}
    partition = Partition(graph, assignment, {"cut_edges": cut_edges})
    # 112    111
    # 112 -> 121
    # 222    222
    flip = {4: 2, 2: 1, 5: 1}

    new_partition = Partition(parent=partition, flips=flip)

    result = new_partition["cut_edges"]

    naive_cut_edges = {
        tuple(sorted(edge))
        for edge in graph.edges if new_partition.crosses_parts(edge)
    }
    assert result == naive_cut_edges
Example #16
0
def test_data_tally_mimics_old_tally_usage(graph_with_random_data_factory):
    graph = graph_with_random_data_factory(["total"])

    # Make a DataTally the same way you make a Tally
    updaters = {"total": DataTally("total", alias="total")}
    assignment = {i: 1 if i in range(4) else 2 for i in range(9)}

    partition = Partition(graph, assignment, updaters)
    expected_total_in_district_one = sum(graph.nodes[i]["total"] for i in range(4))
    assert partition["total"][1] == expected_total_in_district_one
Example #17
0
def relabel_by_dem_vote_share(part, election):
    """
    Renumbers districts by DEM vote share, 0-indexed
    """
    dem_percent = election.percents('Democratic')
    unranked_to_ranked = sorted([(list(part.parts.keys())[x], dem_percent[x])
                                  for x in range(0, len(part))],
                                  key=operator.itemgetter(1))
    unranked_to_ranked_list = [x[0] for x in unranked_to_ranked]
    unranked_to_ranked = {unranked_to_ranked[x][0]:x for x in range(0, len(part))}
    newpart = Partition(part.graph, {x:unranked_to_ranked[part.assignment[x]] for x in part.graph.nodes}, part.updaters)
    return newpart
Example #18
0
def test_works_when_no_flips_occur():
    graph = Graph([(0, 1), (1, 2), (2, 3), (3, 0)])
    for node in graph:
        graph.nodes[node]["pop"] = node + 1
    partition = Partition(graph, {0: 0, 1: 0, 2: 1, 3: 1}, {"pop": Tally("pop")})

    chain = MarkovChain(lambda p: p.flip({}), [], always_accept, partition, 10)

    expected = {0: 3, 1: 7}

    for partition in chain:
        assert partition["pop"] == expected
Example #19
0
def test():

    graph_path = "./Data/PA_VTDALL.json"
    graph = Graph.from_json(graph_path)
    k = 18
    ep = 0.05
    unit_id = "GEOID10"
    pop_col = "TOT_POP"

    plot_path = "./Data/VTD_FINAL"
    unit_df = gpd.read_file(plot_path)
    division_col = "COUNTYFP10"
    divisions = unit_df[[division_col, 'geometry']].dissolve(by=division_col,
                                                             aggfunc='sum')

    updaters = {"population": updaters.Tally(pop_col, alias="population")}
    cddict = recursive_tree_part(graph,
                                 range(k),
                                 df[pop_col].sum() / k,
                                 pop_col,
                                 .01,
                                 node_repeats=1)
    initial_partition = Partition(graph, cddict, updaters)
    ideal_population = sum(
        initial_partition["population"].values()) / len(initial_partition)
    division_proposal = partial(recom,
                                pop_col=pop_col,
                                pop_target=ideal_population,
                                epsilon=0.05,
                                method=partial(division_bipartition_tree,
                                               division_col=division_col),
                                node_repeats=2)

    chain = MarkovChain(proposal=division_proposal,
                        constraints=[
                            constraints.within_percent_of_ideal_population(
                                initial_partition, 0.05),
                        ],
                        accept=accept.always_accept,
                        initial_state=initial_partition,
                        total_steps=1000)

    t = 0
    snapshot = 100
    for part in chain:
        if t % snapshot == 0:
            draw_graph(graph,
                       part.assignment,
                       unit_df,
                       divisions,
                       './chain_' + str(t) + '.png',
                       geo_id=unit_id)
        t += 1
Example #20
0
def make_partitions(n):
    '''
    Returns a list of every possible partition
    on the nXn grid. This is nearly instantaneous for n = 3-5,
    and takes about 60s for n=6.
    '''
    partitions = []
    assignment_dict = make_assignment_dicts(n)
    grid = Grid((n, n))
    for i in range(len(assignment_dict)):
        partition = Partition(grid.graph, assignment_dict[i])
        partitions.append(partition)
    return partitions
Example #21
0
def test_cut_edges_by_part_gives_same_total_edges_as_naive_method(
        three_by_three_grid):
    graph = three_by_three_grid
    assignment = {0: 1, 1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2}
    updaters = {"cut_edges_by_part": cut_edges_by_part}
    partition = Partition(graph, assignment, updaters)
    # 112    111
    # 112 -> 121
    # 222    222
    flip = {4: 2, 2: 1, 5: 1}

    new_partition = Partition(parent=partition, flips=flip)

    result = new_partition["cut_edges_by_part"]
    naive_cut_edges = {
        tuple(sorted(edge))
        for edge in graph.edges if new_partition.crosses_parts(edge)
    }

    assert naive_cut_edges == {
        tuple(sorted(edge))
        for part in result for edge in result[part]
    }
 def toChain(self, initial_partition):
     """Returns chain with instance variables of self NoInitialChain and
     parameter initial_partition."""
     return MarkovChain(
         proposal=self.proposal,
         constraints=self.constraints,
         accept=self.accept,
         # Declares new Partition with identical instances in order to avoid
         # attempting to access parent
         initial_state=Partition(initial_partition.graph,
                                 assignment=initial_partition.assignment,
                                 updaters=initial_partition.updaters),
         total_steps=self.total_steps
     )
def compute_cross_edge(graph, partition):
    """
    The function finds the edges that cross from one partition to another
    partition
    Parameters:
        graph (Graph): The given graph represent state information
        partition (Partition): the partition of the given graph
    Returns:
        list: the list of edges that cross two partitions
    """
    cross_list = []
    for n in graph.edges:
        if Partition.crosses_parts(partition, n):
            cross_list.append(n)
    return cross_list  # cut edges of partition
def test_repeatable(three_by_three_grid):
    from gerrychain import (
        MarkovChain,
        Partition,
        accept,
        constraints,
        proposals,
        updaters,
    )

    partition = Partition(
        three_by_three_grid,
        {0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2, 9: 2},
        {"cut_edges": updaters.cut_edges},
    )
    chain = MarkovChain(
        proposals.propose_random_flip,
        constraints.single_flip_contiguous,
        accept.always_accept,
        partition,
        20,
    )
    # Note: these might not even be the actual expected flips
    expected_flips = [
        None,
        {2: 2},
        {4: 2},
        {6: 1},
        {1: 2},
        {7: 1},
        {0: 2},
        {3: 2},
        {7: 2},
        {3: 1},
        {4: 1},
        {7: 1},
        {8: 1},
        {8: 2},
        {8: 1},
        {8: 2},
        {3: 2},
        {4: 2},
        {7: 2},
        {3: 1},
    ]
    flips = [partition.flips for partition in chain]
    print(flips)
    assert flips == expected_flips
Example #25
0
def tree_grid(n=20, m=20, k=40, varepsilon=0.01):
    graph = nx.grid_graph([n, m])

    for node in graph.nodes():
        graph.node[node]["population"] = 1

    cddict = recursive_tree_part(graph, range(k), m * n / k, "population",
                                 varepsilon, 1)

    updater = {"cut_edges": cut_edges}

    initial_partition = Partition(graph, cddict, updater)

    dg = nx.Graph()
    for edge in initial_partition["cut_edges"]:
        dg.add_edge(cddict[edge[0]], cddict[edge[1]])

    return dg
def buildPartition(graph, mean):
    # horizontal = []
    assignment = {}
    for x in graph.node():
        if graph.node[x]['C_X'] < mean:
            assignment[x] = -1
        else:
            assignment[x] = 1

    updaters = {
        'population': Tally('population'),
        "boundary": bnodes_p,
        'cut_edges': cut_edges,
        'step_num': step_num,
        'b_nodes': b_nodes_bi,
        'base': new_base,
        'geom': geom_wait,
    }

    grid_partition = Partition(graph, assignment=assignment, updaters=updaters)
    return grid_partition
def factor_seed(graph, k, pop_tol, pop_col):
    '''
    Recursively partitions a graph into k districts.

    Returns an assignment.
    '''
    total_population = sum([graph.nodes[n][pop_col] for n in graph.nodes])
    pop_target = total_population / k
    num_d = 1
    ass = {x: 0 for x in graph.nodes}
    while num_d != k:
        for r in range(2, int(k / num_d) + 1):
            if int(k / num_d) % r == 0:
                print("Splitting from {:d} down to {:d}".format(
                    int(num_d), int(r * num_d)))
                ass = split_districts(Partition(graph, ass), r,
                                      pop_target * k / num_d / r, pop_col,
                                      pop_tol / k)
                num_d *= r
                break
    return ass
Example #28
0
def test_contiguous_components(graph):
    partition = Partition(graph, {
        0: 1,
        1: 1,
        2: 1,
        3: 2,
        4: 2,
        5: 2,
        6: 1,
        7: 1,
        8: 1
    })

    components = contiguous_components(partition)

    assert len(components[1]) == 2
    assert len(components[2]) == 1

    assert set(frozenset(g.nodes) for g in components[1]) == {
        frozenset([0, 1, 2]),
        frozenset([6, 7, 8]),
    }

    assert set(components[2][0].nodes) == {3, 4, 5}
Example #29
0
#for n in graph.nodes():
#    graph.node[n]["tree_plan"] = tree_dict[graph.node[n]["GEOID10"]]

with open("./Outputs/build/init31.json", 'r') as f:
    tree_dict = json.load(f)


tree_dict = {int(k):int(v) for k,v in tree_dict.items()}


print('loaded new plan')


#initial_partition = Partition(graph, "tree_plan", updater)
initial_partition = Partition(graph, tree_dict, updater)

print("built initial partition")


ideal_population = sum(initial_partition["population"].values()) / len(
    initial_partition
)
# print(ideal_population)

tree_proposal = partial(
    recom, pop_col="TOT_POP", pop_target=ideal_population, epsilon=0.01, node_repeats=1, method = bipartition_tree_random
)

compactness_bound = constraints.UpperBound(
    lambda p: len(p["cut_edges"]), 2 * len(initial_partition["cut_edges"])
Example #30
0
def example_partition():
    graph = Graph.from_networkx(networkx.complete_graph(3))
    assignment = {0: 1, 1: 1, 2: 2}
    partition = Partition(graph, assignment, {"cut_edges": cut_edges})
    return partition