예제 #1
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
예제 #2
0
def test_recom_works_as_a_proposal(partition_with_pop):
    graph = partition_with_pop.graph
    ideal_pop = sum(graph.nodes[node]["pop"] for node in graph) / 2
    proposal = functools.partial(
        recom, pop_col="pop", pop_target=ideal_pop, epsilon=0.25, node_repeats=5
    )
    constraints = [within_percent_of_ideal_population(partition_with_pop, 0.25, "pop")]

    chain = MarkovChain(proposal, constraints, lambda x: True, partition_with_pop, 100)

    for state in chain:
        assert contiguous(state)
예제 #3
0
def test_pa_freeze():
    from gerrychain import (
        GeographicPartition,
        Graph,
        MarkovChain,
        proposals,
        updaters,
        constraints,
        accept,
    )
    import hashlib
    from gerrychain.proposals import recom
    from functools import partial

    graph = Graph.from_json("docs/user/PA_VTDs.json")

    my_updaters = {"population": updaters.Tally("TOTPOP", alias="population")}
    initial_partition = GeographicPartition(graph,
                                            assignment="CD_2011",
                                            updaters=my_updaters)

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

    # We use functools.partial to bind the extra parameters (pop_col, pop_target, epsilon, node_repeats)
    # of the recom proposal.
    proposal = partial(recom,
                       pop_col="TOTPOP",
                       pop_target=ideal_population,
                       epsilon=0.02,
                       node_repeats=2)

    pop_constraint = constraints.within_percent_of_ideal_population(
        initial_partition, 0.02)

    chain = MarkovChain(
        proposal=proposal,
        constraints=[pop_constraint],
        accept=accept.always_accept,
        initial_state=initial_partition,
        total_steps=100,
    )

    result = ""
    for count, partition in enumerate(chain):
        result += str(list(sorted(partition.population.values())))
        result += str(len(partition.cut_edges))
        result += str(count) + "\n"

    assert hashlib.sha256(result.encode()).hexdigest(
    ) == "3bef9ac8c0bfa025fb75e32aea3847757a8fba56b2b2be6f9b3b952088ae3b3c"
 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
     )
예제 #5
0
def run_chain(disc, disc_partition, num_steps):



    exp_chain = MarkovChain(slow_reversible_propose_bi ,Validator([single_flip_contiguous#,boundary_condition
            ]), accept = cut_accept, initial_state=disc_partition,
            total_steps =  num_steps)

    t = 0
    for observation in exp_chain:
        t += 1



    return observation
예제 #6
0
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
예제 #7
0
def test_elections_match_the_naive_computation(partition_with_election):
    chain = MarkovChain(
        propose_random_flip,
        Validator([no_vanishing_districts, reject_half_of_all_flips]),
        lambda x: True,
        partition_with_election,
        total_steps=100,
    )

    for partition in chain:
        election_view = partition["Mock Election"]
        expected_party_totals = {
            "D": expected_tally(partition, "D"),
            "R": expected_tally(partition, "R"),
        }
        assert expected_party_totals == election_view.totals_for_party
예제 #8
0
def test_perimeter_match_naive_perimeter_at_every_step():
    partition = Grid((10, 10), with_diagonals=True)

    chain = MarkovChain(
        propose_random_flip,
        [single_flip_contiguous, no_vanishing_districts],
        always_accept,
        partition,
        1000,
    )

    def get_exterior_boundaries(partition):
        graph_boundary = partition["boundary_nodes"]
        exterior = defaultdict(lambda: 0)
        for node in graph_boundary:
            part = partition.assignment[node]
            exterior[part] += partition.graph.nodes[node]["boundary_perim"]
        return exterior

    def get_interior_boundaries(partition):
        cut_edges = {
            edge
            for edge in partition.graph.edges if partition.crosses_parts(edge)
        }
        interior = defaultdict(int)
        for edge in cut_edges:
            for node in edge:
                interior[partition.assignment[node]] += partition.graph.edges[
                    edge]["shared_perim"]
        return interior

    def expected_perimeter(partition):
        interior_boundaries = get_interior_boundaries(partition)
        exterior_boundaries = get_exterior_boundaries(partition)
        expected = {
            part: interior_boundaries[part] + exterior_boundaries[part]
            for part in partition.parts
        }
        return expected

    for state in chain:
        expected = expected_perimeter(state)
        assert expected == state["perimeter"]
예제 #9
0
def run_GerryChain_heuristic(G, population_deviation, k, iterations):

    my_updaters = {"population": updaters.Tally("TOTPOP", alias="population")}
    start = recursive_tree_part(
        G, range(k),
        sum(G.nodes[i]["TOTPOP"] for i in G.nodes()) / k, "TOTPOP",
        population_deviation / 2, 1)
    initial_partition = GeographicPartition(G, start, updaters=my_updaters)

    proposal = partial(recom,
                       pop_col="TOTPOP",
                       pop_target=sum(G.nodes[i]["TOTPOP"]
                                      for i in G.nodes()) / k,
                       epsilon=population_deviation / 2,
                       node_repeats=2)

    compactness_bound = constraints.UpperBound(
        lambda p: len(p["cut_edges"]),
        1.5 * len(initial_partition["cut_edges"]))

    pop_constraint = constraints.within_percent_of_ideal_population(
        initial_partition, population_deviation / 2)

    my_chain = MarkovChain(proposal=proposal,
                           constraints=[pop_constraint, compactness_bound],
                           accept=accept.always_accept,
                           initial_state=initial_partition,
                           total_steps=iterations)

    min_cut_edges = sum(G[i][j]['edge_length'] for i, j in G.edges)
    print("In GerryChain heuristic, current # of cut edges: ", end='')
    print(min_cut_edges, ",", sep='', end=' ')
    for partition in my_chain:
        current_cut_edges = sum(G[i][j]['edge_length']
                                for i, j in partition["cut_edges"])
        print(current_cut_edges, ",", sep='', end=' ')
        if current_cut_edges < min_cut_edges:
            best_partition = partition
            min_cut_edges = current_cut_edges

    print("Best heuristic solution has # cut edges =", min_cut_edges)
    return ([[i for i in G.nodes if best_partition.assignment[i] == j]
             for j in range(k)], min_cut_edges)
예제 #10
0
def test_cut_edges_matches_naive_cut_edges_at_every_step(
        proposal, number_of_steps):
    partition = Grid((10, 10), with_diagonals=True)

    chain = MarkovChain(
        proposal,
        [single_flip_contiguous, no_vanishing_districts],
        always_accept,
        partition,
        number_of_steps,
    )

    for state in chain:
        naive_cut_edges = {
            edge
            for edge in state.graph.edges if state.crosses_parts(edge)
        }

        assert naive_cut_edges == state["cut_edges"]
예제 #11
0
def test_tally_matches_naive_tally_at_every_step():
    partition = Grid((10, 10), with_diagonals=True)

    chain = MarkovChain(
        propose_random_flip,
        [single_flip_contiguous, no_vanishing_districts],
        always_accept,
        partition,
        1000,
    )

    def get_expected_tally(partition):
        expected = defaultdict(int)
        for node in partition.graph.nodes:
            part = partition.assignment[node]
            expected[part] += partition.graph.nodes[node]["population"]
        return expected

    for state in chain:
        expected = get_expected_tally(state)
        assert expected == state["population"]
예제 #12
0
def shift_flip(partition, ep, ideal_pop, max_steps=150000, chain_bound=.02):

    #TODO: Amy, where do we think this function should be stored? Its
    #needed in the Chain I run within this shift function
    def pop_accept(partition):
        if not partition.parent:
            return True
        proposal_dev_score = max_pop_dev(partition, ideal_pop)
        parent_dev_score = max_pop_dev(partition.parent, ideal_pop)
        if proposal_dev_score < parent_dev_score:
            return True
        else:
            draw = random.random()
            return draw < chain_bound

    # print("ideal pop", ideal_pop)

    pop_tol_initial = max_pop_dev(partition, ideal_pop)
    # print("pop tol initial", pop_tol_initial)
    #if error again from initial state, just make constraint value
    chain = MarkovChain(proposal=propose_random_flip,
                        constraints=[
                            constraints.within_percent_of_ideal_population(
                                partition, pop_tol_initial + .05),
                            single_flip_contiguous
                        ],
                        accept=pop_accept,
                        initial_state=partition,
                        total_steps=max_steps)

    step_Num = 0
    for step in chain:
        partition = step
        #   print("step num", step_Num, max_pop_dev(partition, ideal_pop))
        if max_pop_dev(partition, ideal_pop) <= ep:
            break
        step_Num += 1

    return Partition(partition.graph, partition.assignment, partition.updaters)
예제 #13
0
def run_chain(adj_graph, elections, total_steps=100):
    my_updaters = {
        "population": updaters.Tally("population"),
        "cut_edges": cut_edges,
        "elections": lambda x: [elec.alias for elec in elections],
        "expected_seat_share": expected_seat_share_updater
    }
    election_updaters = {election.name: election for election in elections}
    my_updaters.update(election_updaters)

    initial_partition = GeographicPartition(adj_graph,
                                            assignment="initial_plan",
                                            updaters=my_updaters)
    ideal_population = sum(
        initial_partition["population"].values()) / len(initial_partition)
    proposal = partial(recom,
                       pop_col="population",
                       pop_target=ideal_population,
                       epsilon=0.01,
                       node_repeats=2)
    pop_constraint = constraints.within_percent_of_ideal_population(
        initial_partition, 0.01)
    chain = MarkovChain(proposal=proposal,
                        constraints=[
                            pop_constraint,
                        ],
                        accept=accept.always_accept,
                        initial_state=initial_partition,
                        total_steps=total_steps)

    return pd.DataFrame({
        ix: {
            "cut_edges": len(partition["cut_edges"]),
            "expected_R_seats": partition["expected_seat_share"]
        }
        for ix, partition in enumerate(chain)
    }).T
예제 #14
0
def debug():

    num_steps = 100000
    disc = integral_disc(10)
    disc_partition = initial_partition(disc)
    exp_chain = MarkovChain(slow_reversible_propose_bi ,Validator([single_flip_contiguous#,boundary_condition
            ]), accept = cut_accept, initial_state=disc_partition,
            total_steps =  num_steps)

    t = 0
    for observation in exp_chain:
        t += 1


    bd = convert_partition_to_boundary(disc, observation)

    Facefinder.draw_with_location(disc)
    Facefinder.draw_with_location(bd, "red")

    path = convert_path_graph_to_sequence_of_nodes(bd)

    aligned_boundary = conformally_align(path)

    return aligned_boundary
예제 #15
0
def chain(iterations):
    idef = random.randint(1, 10000)
    graph = Graph.from_json("../data/PA_init/PA_VTD.json")

    election = Election("SEN12", {"Dem": "USS12D", "Rep": "USS12R"})

    initial_partition = GeographicPartition(
        graph,
        assignment="2011_PLA_1",
        updaters={
            "cut_edges": cut_edges,
            "population": Tally("TOT_POP", alias="population"),
            "SEN12": election
        }
    )

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

    # We use functools.partial to bind the extra parameters (pop_col, pop_target, epsilon, node_repeats)
    # of the recom proposal.

    proposal = partial(recom,
                       pop_col="TOT_POP",
                       pop_target=ideal_population,
                       epsilon=0.02,
                       node_repeats=2
                      )

    chain = MarkovChain(
            proposal=proposal,
            constraints=[],
            accept=contiguous,
            initial_state=initial_partition,
            total_steps=85*iterations + 17000
        )

    count = 0
    metrics = []
    boundary_nodes = []
    boundary_weighted = []
    for partition in chain.with_progress_bar(): 
        mm = mean_median(partition["SEN12"])
        p = pp(partition)
        bias = partisan_bias(partition["SEN12"])
        gini = partisan_gini(partition["SEN12"])
        gap = efficiency_gap(partition["SEN12"])
        cut = len(partition["cut_edges"])
        if count >= 17000:
            if count % 85 == 0: 
                metrics.append((mm, p, bias, gini, gap, cut, partition["SEN12"].wins("Rep")))
                nodes = [0]*8921
                bnodes = [0]*8921
                for edge in partition["cut_edges"]:
                    nodes[edge[0]] = 1
                    nodes[edge[1]] = 1
                    bnodes[edge[0]] += 1
                    bnodes[edge[1]] += 1
                boundary_nodes.append(nodes)
                boundary_weighted.append(bnodes)

                assign = {i: partition.assignment[i] for i in partition.assignment}
                shape["CD"] = shape.index.map(assign)
                this_map = shape.dissolve(by='CD')
                this_map.plot(color='white', edgecolor='black')
                plt.axis('off')
                fig = plt.gcf()
                fig.set_size_inches((15,9), forward=False)
                fig.savefig("../images/PA_neutral/" + str(idef) + str(int((count-17000)/85)+1) + ".png", dpi=600, bbox_inches="tight", pad_inches=0)

                plt.close()

            if count % 8500 == 0: 
                print(idef, count, mm, p, bias, gini, gap, cut, partition["SEN12"].wins("Rep"))
        else:
            if count%1000 == 0:
                print(idef, "Mixing...... Iteration", count, "/17000")
        count += 1

    return metrics, boundary_nodes, boundary_weighted, idef
    grid_partition["population"].values()) / len(grid_partition)

tree_proposal = partial(
    recom,
    pop_col="population",
    pop_target=ideal_population,
    epsilon=0.05,
    node_repeats=1,
)

# ######BUILD AND RUN FIRST MARKOV CHAIN

recom_chain = MarkovChain(
    tree_proposal,
    constraints=[popbound],
    accept=always_accept,
    initial_state=grid_partition,
    total_steps=100,
)

for part in recom_chain:
    pass

plt.figure()
nx.draw(
    graph,
    pos={x: x
         for x in graph.nodes()},
    node_color=[part.assignment[x] for x in graph.nodes()],
    node_size=ns,
    node_shape="s",
예제 #17
0
            #########Setup Proposal
            ideal_population = sum(grid_partition["population"].values()) / len(grid_partition)

            tree_proposal = partial(recom,
                                   pop_col="population",
                                   pop_target=ideal_population,
                                   epsilon=0.05,
                                   node_repeats=1
                                  )

            #######BUILD MARKOV CHAINS


            exp_chain = MarkovChain(slow_reversible_propose_bi ,Validator([single_flip_contiguous, popbound#,boundary_condition
            ]), accept = cut_accept, initial_state=grid_partition,
            total_steps =  10000000)





            #########Run MARKOV CHAINS

            rsw = []
            rmm = []
            reg = []
            rce = []
            rbn=[]
            waits= []
                   epsilon=0.05,
                   node_repeats=3)

compactness_bound = constraints.UpperBound(lambda p: len(p["cut_edges"]),
                                           len(initial_partition["cut_edges"]))

county_splits_bound = constraints.UpperBound(
    lambda p: calc_splits(p["county_splits"]),
    calc_splits(initial_partition["county_splits"]))

chain = MarkovChain(
    proposal=proposal,
    constraints=[
        constraints.within_percent_of_ideal_population(initial_partition,
                                                       0.05),
        compactness_bound, county_splits_bound
    ],
    accept=accept.always_accept,
    initial_state=initial_partition,
    total_steps=steps,
)

BVAP = []
HVAP = []
VAP = []
POP = []
for i in election_names:
    vars()["{}".format(i)] = []
for i in election_names:
    vars()["{}wins".format(i)] = []
for i in election_names:
        return (partition["P1 vs P2"].wins("P2")/k_partitions)*100

def equal_check(partition, party):
    for number in range(1, k_partitions+1):
        if partition["P1 vs P2"].wins("P1")+partition["P1 vs P2"].wins("P2") == k_partitions + number:
            return ((partition["P1 vs P2"].wins(party)/k_partitions)*100)-((100/k_partitions)/2)*number
    raise error
    
ideal_population = sum(init_part["population"].values()) / len(init_part)
popbound = within_percent_of_ideal_population(init_part, 0.1)
cutedgebound = UpperBound(lambda part: len(part["cut_edges"]), 400)

flip_steps = 250000
flip_chain = MarkovChain(
propose_random_flip,
Validator([single_flip_contiguous, popbound, cutedgebound]), 
    accept = always_accept, 
    initial_state = init_part, 
    total_steps = flip_steps, )

flip_p1_seats = []
for part in flip_chain:
    flip_p1_seats.append(part["P1 vs P2"].wins("P1"))
plt.figure()
nx.draw(
graph,
pos = {x: x for x in graph.nodes()},
node_color = [dict(part.assignment)[x]
for x in graph.nodes()],
node_size = node_size,
node_shape = "p",
cmap = "Set2",)
예제 #20
0
    recom,
    pop_col="TAPERSONS",
    pop_target=ideal_population,
    epsilon=0.005,
    node_repeats=1,
    method=my_uu_bipartition_tree_random)  # bipartition_tree_random
#)

compactness_bound = constraints.UpperBound(
    lambda p: len(p["cut_edges"]), 2 * len(initial_partition["cut_edges"]))

chain = MarkovChain(
    proposal=tree_proposal,
    constraints=[
        #constraints.within_percent_of_ideal_population(initial_partition, 0.013),
        compactness_bound  #,  single_flip_contiguous#no_more_discontiguous
    ],
    accept=accept.always_accept,
    initial_state=initial_partition,
    total_steps=20000,
)

print("initialized chain")

with open(newdir + "Start_Values.txt", "w") as f:
    f.write("Values for Starting Plan: Tree Recursive\n \n ")
    f.write("Initial Cut: " + str(len(initial_partition["cut_edges"])))
    f.write("\n")
    f.write("\n")

    for elect in range(num_elections):
        f.write(election_names[elect] + "District Percentages" + str(
def produce_sample(graph, k, tag, sample_size = 500, chaintype='tree'):
    #Samples k partitions of the graph, stores the cut edges and records them graphically
    #Also stores vote histograms, and returns most extreme partitions.

    print("producing sample")
    updaters = {'population': Tally('population'),
                'cut_edges': cut_edges,
                'step_num': step_num,
                }
    for edge in graph.edges():
        graph[edge[0]][edge[1]]['cut_times'] = 0

    
    for n in graph.nodes():
        #graph.nodes[n]["population"] = 1 #graph.nodes[n]["POP10"] #This is something gerrychain will refer to for checking population balance
        graph.nodes[n]["last_flipped"] = 0
        graph.nodes[n]["num_flips"] = 0
    print("set up chain")
    ideal_population= sum( graph.nodes[x]["population"] for x in graph.nodes())/k

    initial_partition = Partition(graph, assignment='part', updaters=updaters)
    pop1 = .05
    print("popbound")
    popbound = within_percent_of_ideal_population(initial_partition, pop1)

    if chaintype == "tree":
        tree_proposal = partial(recom, pop_col="population", pop_target=ideal_population, epsilon=pop1,
                                node_repeats=1, method=facefinder.my_mst_bipartition_tree_random)

    elif chaintype == "uniform_tree":
        tree_proposal = partial(recom, pop_col="population", pop_target=ideal_population, epsilon=pop1,
                                node_repeats=1, method=facefinder.my_uu_bipartition_tree_random)
    else:
        print("Chaintype used: ", chaintype)
        raise RuntimeError("Chaintype not recongized. Use 'tree' or 'uniform_tree' instead")

    
    exp_chain = MarkovChain(tree_proposal, Validator([popbound]), accept=always_true, initial_state=initial_partition, total_steps=sample_size)
    
    

    z = 0
    num_cuts_list = []
    seats_won_table = []
    best_left = np.inf
    best_right = -np.inf
    print("begin chain")
    for part in exp_chain:


        
        z += 1
        if z % 100 == 0:
            print("step ", z)
        seats_won = 0

        for edge in part["cut_edges"]:
            graph[edge[0]][edge[1]]["cut_times"] += 1
        for i in range(k):
            rep_votes = 0
            dem_votes = 0
            for n in graph.nodes():
                if part.assignment[n] == i:
                    rep_votes += graph.nodes[n]["EL16G_PR_R"]
                    dem_votes += graph.nodes[n]["EL16G_PR_D"]
            total_seats = int(rep_votes > dem_votes)
            seats_won += total_seats
        # total seats won by rep
        seats_won_table.append(seats_won)
        # save gerrymandered partitionss
        if seats_won < best_left:
            best_left = seats_won
            #left_mander = copy.deepcopy(part.parts)
        if seats_won > best_right:
            best_right = seats_won

            #right_mander = copy.deepcopy(part.parts)
        #print("finished round"
    
    print("max", best_right, "min:", best_left)
    
    plt.figure()
    plt.hist(seats_won_table, bins = 10)
    
    name = "./plots/seats_histogram_metamander" + tag +".png"
    plt.savefig(name)
    plt.close()    
        
    edge_colors = [graph[edge[0]][edge[1]]["cut_times"] for edge in graph.edges()]
    
    pos=nx.get_node_attributes(graph, 'pos')
    

    plt.figure()
    plt.hist(seats_won_table, bins=10)
    mean = sum(seats_won_table) / len(seats_won_table)
    std = np.std(seats_won_table)
    # plt.close()
    # title = 'mean: ' + str(mean) + ' standard deviation: ' + str(std)
    # plt.title(title)
    # name = "./plots/seats_hist/seats_histogram" + tag + ".png"
    # plt.savefig(name)
    # plt.close()

    # edge_colors = [graph[edge[0]][edge[1]]["cut_times"] for edge in graph.edges()]
    #
    # plt.figure()
    # nx.draw(graph, pos=nx.get_node_attributes(graph, 'pos'), node_size=0,
    #         edge_color=edge_colors, node_shape='s',
    #         cmap='magma', width=1)
    # plt.savefig("./plots/edges_plots/edges" + tag + ".png")
    # plt.close()

    return mean, std, graph
def produce_gerrymanders(graph, k, tag, sample_size, chaintype):
    # Samples k-partitions of the graph
    # stores vote histograms, and returns most extreme partitions.
    for node in graph.nodes():
        graph.nodes[node]["last_flipped"] = 0
        graph.nodes[node]["num_flips"] = 0

    ideal_population = sum(graph.nodes[x][config["POPULATION_COLUMN"]] for x in graph.nodes()) / k
    election = Election(
        config['ELECTION_NAME'],
        {'PartyA': config['PARTY_A_COL'], 'PartyB': config['PARTY_B_COL']},
        alias=config['ELECTION_ALIAS']
    )
    updaters = {'population': Tally(config['POPULATION_COLUMN']),
                'cut_edges': cut_edges,
                'step_num': step_num,
                config['ELECTION_ALIAS'] : election
                }
    initial_partition = Partition(graph, assignment=config['ASSIGNMENT_COLUMN'], updaters=updaters)
    popbound = within_percent_of_ideal_population(initial_partition, config['POPULATION_EPSILON'])

    if chaintype == "tree":
        tree_proposal = partial(recom, pop_col=config["POPULATION_COLUMN"], pop_target=ideal_population,
                           epsilon=config['POPULATION_EPSILON'], node_repeats=config['NODE_REPEATS'],
                           method=facefinder.my_mst_bipartition_tree_random)

    elif chaintype == "uniform_tree":
        tree_proposal = partial(recom, pop_col=config["POPULATION_COLUMN"], pop_target=ideal_population,
                           epsilon=config['POPULATION_EPSILON'], node_repeats=config['NODE_REPEATS'],
                           method=facefinder.my_uu_bipartition_tree_random)
    else:
        print("Chaintype used: ", chaintype)
        raise RuntimeError("Chaintype not recognized. Use 'tree' or 'uniform_tree' instead")

    exp_chain = MarkovChain(tree_proposal, Validator([popbound]), accept=accept.always_accept, initial_state=initial_partition,
                            total_steps=sample_size)

    seats_won_table = []
    best_left = np.inf
    best_right = -np.inf
    for ctr, part in enumerate(exp_chain):
        seats_won = 0

        if ctr % 100 == 0:
            print("step ", ctr)
        for i in range(k):
            rep_votes = 0
            dem_votes = 0
            for node in graph.nodes():
                if part.assignment[node] == i:
                    rep_votes += graph.nodes[node]["EL16G_PR_R"]
                    dem_votes += graph.nodes[node]["EL16G_PR_D"]
            total_seats = int(rep_votes > dem_votes)
            seats_won += total_seats
        # total seats won by rep
        seats_won_table.append(seats_won)
        # save gerrymandered partitions
        if seats_won < best_left:
            best_left = seats_won
            left_mander = copy.deepcopy(part.parts)
        if seats_won > best_right:
            best_right = seats_won
            right_mander = copy.deepcopy(part.parts)
        # print("finished round"

    print("max", best_right, "min:", best_left)

    plt.figure()
    plt.hist(seats_won_table, bins=10)

    name = "./plots/large_sample/seats_hist/seats_histogram_orig" + tag + ".png"
    plt.savefig(name)
    plt.close()
    return left_mander, right_mander
예제 #23
0
def run_simple(graph):
    election = Election("2016 President", {
        "Democratic": "T16PRESD",
        "Republican": "T16PRESR"
    },
                        alias="2016_President")

    initial_partition = Partition(graph,
                                  assignment="2011_PLA_1",
                                  updaters={
                                      "2016_President":
                                      election,
                                      "population":
                                      Tally("TOT_POP", alias="population"),
                                      "perimeter":
                                      perimeter,
                                      "exterior_boundaries":
                                      exterior_boundaries,
                                      "interior_boundaries":
                                      interior_boundaries,
                                      "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',
                                                    "COUNTYFP10"),
                                      "black_population":
                                      Tally("BLACK_POP",
                                            alias="black_population"),
                                  })

    efficiency_gaps = []
    wins = []
    beta = 0
    wp = 1
    wi = 1
    wc = 0
    wm = 1

    def accept(partition):
        return (metro_scoring_prob(partition, beta, wp, wi, wc, wm))

    is_valid = Validator([single_flip_contiguous, districts_within_tolerance])
    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)

    for partition in chain:
        if (hasattr(partition, 'accepted') and partition.accepted):
            efficiency_gaps.append(
                gerrychain.scores.efficiency_gap(partition["2016_President"]))
            wins.append(partition["2016_President"].wins("Democratic"))
    return (efficiency_gaps, wins, partition)
예제 #24
0
        partial(recom,
                pop_col="TOTPOP",
                pop_target=totpop[i] / num_districts,
                epsilon=0.02,
                node_repeats=1))

    compactness_bounds.append(
        constraints.UpperBound(lambda p: len(p["cut_edges"]),
                               2 * len(initial_partitions[i]["cut_edges"])))

    chains.append(
        MarkovChain(
            proposal=proposals[i],
            constraints=[
                constraints.within_percent_of_ideal_population(
                    initial_partitions[i], 0.05), compactness_bounds[i]
                #constraints.single_flip_contiguous#no_more_discontiguous
            ],
            accept=accept.always_accept,
            initial_state=initial_partitions[i],
            total_steps=1000))

cuts = [[], [], [], []]
BVAPS = [[], [], [], []]

for i in range(4):
    t = 0
    for part in chains[i]:
        cuts[i].append(len(part["cut_edges"]))
        BVAPS[i].append(sorted(part["BVAP"].percents("BVAP")))
        t += 1
        if t % 100 == 0:
예제 #25
0
def chain(iterations):
    idef = random.randint(1, 10000)
    graph = Graph.from_json("./PA_VTD.json")

    election = Election("SEN12", {"Dem": "USS12D", "Rep": "USS12R"})

    initial_partition = GeographicPartition(graph,
                                            assignment="2011_PLA_1",
                                            updaters={
                                                "cut_edges":
                                                cut_edges,
                                                "population":
                                                Tally("TOT_POP",
                                                      alias="population"),
                                                "SEN12":
                                                election
                                            })

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

    # We use functools.partial to bind the extra parameters (pop_col, pop_target, epsilon, node_repeats)
    # of the recom proposal.

    proposal = partial(recom,
                       pop_col="TOT_POP",
                       pop_target=ideal_population,
                       epsilon=0.02,
                       node_repeats=2)

    chain = MarkovChain(proposal=proposal,
                        constraints=[republican_constraint],
                        accept=contiguous,
                        initial_state=initial_partition,
                        total_steps=iterations + 100)

    count = 0
    metrics = []
    boundary_nodes = []
    boundary_weighted = []
    for partition in chain.with_progress_bar():
        mm = mean_median(partition["SEN12"])
        p = pp(partition)
        bias = partisan_bias(partition["SEN12"])
        gini = partisan_gini(partition["SEN12"])
        gap = efficiency_gap(partition["SEN12"])
        cut = len(partition["cut_edges"])
        if count >= 100:
            metrics.append((mm, p, bias, gini, gap, cut))
            nodes = [0] * 8921
            bnodes = [0] * 8921
            for edge in partition["cut_edges"]:
                nodes[edge[0]] = 1
                nodes[edge[1]] = 1
                bnodes[edge[0]] += 1
                bnodes[edge[1]] += 1
            boundary_nodes.append(nodes)
            boundary_weighted.append(bnodes)
        if count % 100 == 0:
            print(idef, count, mm, p, bias, gini, gap, cut,
                  partition["SEN12"].wins("Rep"))
        count += 1

    return metrics, boundary_nodes, boundary_weighted
예제 #26
0
        ideal_population = sum(gp3["population"].values()) / len(gp3)

        proposal = partial(
            recom,
            pop_col="population",
            pop_target=ideal_population,
            epsilon=0.02,
            node_repeats=1,
        )

        popbound = within_percent_of_ideal_population(gp3, 0.05)

        g3chain = MarkovChain(
            proposal,  # propose_chunk_flip,
            Validator([popbound]),
            accept=always_accept,
            initial_state=gp3,
            total_steps=100,
        )

        t = 0
        for part3 in g3chain:
            t += 1

        print("finished tree walk")

        pos_dict = {n: n for n in graph.nodes()}
        pos = pos_dict

        plt.figure()
        plt.title("Starting Point")
#CHAIN FOR TOTPOP
proposal = partial(recom,
                   pop_col=pop_col,
                   pop_target=tot_pop_col / num_districts,
                   epsilon=0.02,
                   node_repeats=1)

compactness_bound = constraints.UpperBound(
    lambda p: len(p["cut_edges"]), 2 * len(starting_partition["cut_edges"]))

chain = MarkovChain(
    proposal,
    constraints=[
        constraints.within_percent_of_ideal_population(starting_partition,
                                                       0.10), compactness_bound
        #constraints.single_flip_contiguous#no_more_discontiguous
    ],
    accept=accept.always_accept,
    initial_state=starting_partition,
    total_steps=10000)
#CHAIN FOR CPOP

#proposal = partial(
#       recom, pop_col=ccol, pop_target=tot_ccol/num_districts, epsilon=0.02, node_repeats=1
#  )

#compactness_bound = constraints.UpperBound(
#       lambda p: len(p["cut_edges"]), 2 * len(starting_partition["cut_edges"])
#  )

#chain = MarkovChain(
예제 #28
0
tree_proposal = partial(
    recom,
    pop_col="population",
    pop_target=ideal_population,
    epsilon=0.05,
    node_repeats=1,
)

# ######BUILD MARKOV CHAINS
numIters = 10000

recom_chain = MarkovChain(
    tree_proposal,
    Validator([popbound]),
    accept=always_accept,
    initial_state=grid_partition,
    total_steps=numIters,
)

# ########Run MARKOV CHAINS

rsw = []
rmm = []
reg = []
rce = []

expectednumberseats = 0

for part in recom_chain:
    rsw.append(part["Pink-Purple"].wins("Pink"))
예제 #29
0
)
# 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"])
)

chain = MarkovChain(
    proposal=slow_reversible_propose,
    constraints=[
        constraints.within_percent_of_ideal_population(initial_partition, 0.01),
        compactness_bound,  single_flip_contiguous#no_more_discontiguous
    ],
    accept=accept.always_accept,
    initial_state=initial_partition,
    total_steps=10000000,
)

print("initialized chain")


with open(newdir + "Start_Values.txt", "w") as f:
    f.write("Values for Starting Plan: Tree31\n \n ")
    f.write("Initial Cut: " + str(len(initial_partition["cut_edges"])))
    f.write("\n")
    f.write("\n")

    for elect in range(num_elections):
## Setup chain

proposal = partial(recom,
                   pop_col=POP_COL,
                   pop_target=ideal_pop,
                   epsilon=EPS,
                   node_repeats=1)

compactness_bound = constraints.UpperBound(
    lambda p: len(p["cut_edges"]), 2 * len(init_partition["cut_edges"]))

chain = MarkovChain(proposal,
                    constraints=[
                        constraints.within_percent_of_ideal_population(
                            init_partition, EPS), compactness_bound
                    ],
                    accept=accept.always_accept,
                    initial_state=init_partition,
                    total_steps=ITERS)

## Run chain

print("Starting Markov Chain")


def init_chain_results():
    data = {"cutedges": np.zeros(ITERS)}
    parts = {"samples": []}

    for c in DEMO_COLS:
        data[c] = np.zeros((ITERS, NUM_DISTRICTS))