def build_markov_chain(steps, chaintype, ideal_population, grid_partition): if chaintype == "tree": tree_proposal = partial(recom, pop_col="population", pop_target=ideal_population, epsilon=0.05, node_repeats=1, method=my_mst_bipartition_tree_random) # tree_proposal = partial(recom, pop_col="population", pop_target=ideal_population, epsilon=0.1, # node_repeats=1, method=recursive_tree_part) exp_chain = MarkovChain(tree_proposal, Validator([#popbound # ,boundary_condition ]), accept=cut_accept, initial_state=grid_partition, total_steps=steps) if chaintype == "uniform_tree": #tree_proposal = partial(uniform_tree_propose) tree_proposal = partial(recom, pop_col="population", pop_target=ideal_population, epsilon=0.05, node_repeats=1, method=my_uu_bipartition_tree_random) #This tree proposal is returning partitions that are balanced to within epsilon #But its not good enough for this validator. exp_chain = MarkovChain(tree_proposal, Validator([#popbound # ,boundary_condition ]), accept=cut_accept, initial_state=grid_partition, total_steps=steps) return exp_chain
def race_short_burst_chain(column, list_racial_constraints, random_init_partition): goal = race_con(racial_vap_ref, column) found_acceptable = False for i in range(1000): accumulating_demo = race_con( random_init_partition["racial_demographics"], column) print(accumulating_demo) if accumulating_demo >= goal: break racial_constraints = constraints.Validator(list_racial_constraints) chain_race_short_burst = MarkovChain( proposal=proposal, constraints=[ constraints.within_percent_of_ideal_population( random_init_partition, 0.05), racial_constraints ], accept=accept.always_accept, initial_state=random_init_partition, total_steps=10) for part in chain_race_short_burst: race_val = race_con(part["racial_demographics"], column) if race_val >= goal: random_init_partition = part found_acceptable = True break if race_val >= accumulating_demo: random_init_partition = part return random_init_partition, found_acceptable
def hillclimb_run(proposal_func, constraints, initial_partition, num_steps, print_step, print_map=False): print("STARTING HILL") gchain = MarkovChain( proposal_func, constraints=constraints, accept=hill_climb, initial_state=initial_partition, total_steps=num_steps, ) t = 0 cuts = [] for part in gchain: cuts.append(len(part["cut_edges"])) t += 1 if t % print_step == 0: print(t) record_partition(part, t, 'mid_hill', graph_name, exp_num) if print_map: gdf_print_map( part, './opt_plots/Hill_middle_' + str(t) + '_' + str(exp_num) + '.png', gdf, unit_name) print("FINISHED HILL") record_partition(part, t, 'end_hill', graph_name, exp_num) return part, cuts
def anneal_run(proposal_func, constraints, initial_partition, num_steps, print_step, print_map=False): print("STARTING ANNEAL") t = 0 gchain = MarkovChain( proposal_func, constraints=constraints, accept=lambda x: anneal(x, t), initial_state=initial_partition, total_steps=num_steps, ) cuts = [] for part in gchain: cuts.append(len(part["cut_edges"])) t += 1 if t % print_step == 0: print(t) record_partition(part, t, 'mid_anneal', graph_name, exp_num) if print_map: gdf_print_map( part, './opt_plots/Anneal_middle_' + str(t) + '_' + str(exp_num) + '.png', gdf, unit_name) print("FINISHED ANNEAL") record_partition(part, t, 'end_anneal', graph_name, exp_num) return part, cuts
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
def chain_with_election(partition_with_election): return MarkovChain( propose_random_flip, Validator([no_vanishing_districts]), lambda x: True, partition_with_election, total_steps=10, )
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)
def evol_run(crossover_func, crossover_prob, proposal_func, validator, acceptance_func, initial_partitions, num_steps, print_step, print_map=False): print("STARTING EVOL") chain_list = [] for i in range(population_size): gchain = MarkovChain( proposal=proposal_func, constraints=constraints, accept=acceptance_func, initial_state=initial_partitions[i], total_steps=num_steps, ) chain_list.append(gchain) zipped = zip(*chain_list) t = 0 cuts = [] #can change functions so that not every step has mutation + crossover for step in zipped: cuts.append(min([len(part["cut_edges"]) for part in step])) if random.random() < crossover_prob: # can change so that parents are chosen optimally # can change so that multiple crossover steps occur each chain step p1, p2 = random.sample(range(len(step)), 2) part1 = step[p1] part2 = step[p2] child_1, child_2 = crossover_func(part1, part2) chain_list[p1].state = child_1 chain_list[p2].state = child_2 #should these be the parent states instead? chain_list[p1].state.parent = None chain_list[p1].state.parent = None t += 1 if t % print_step == 0: print(t) for part in step: record_partition(part, t, 'mid_evol', graph_name, exp_num) if print_map: gdf_print_map_set( step, './opt_plots/evol_middle_' + str(t) + '_' + str(exp_num) + '.png', gdf, unit_name) print("FINISHED EVOL") end_partitions = [part for part in step] for part in end_partitions: record_partition(part, t, 'end_evol', graph_name, exp_num) return end_partitions, cuts
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
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)
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
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 )
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
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
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
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"]
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)
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"]
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"]
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)
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
) # 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):
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
#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(
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(
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",)
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",
#########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: