def convert_opt_data_to_gerrychain_input(state, opt_data='', plan=None): state_df, adj_graph, _, _ = load_opt_data(state, opt_data) election_df = load_election_df(state, opt_data) state_df = state_df[['population']] metric_df = pd.concat([state_df, election_df], axis=1) if plan is not None: plan_inverse_map = {} for district_ix, tract_ixs in plan.items(): for tix in tract_ixs: plan_inverse_map[tix] = district_ix metric_df['initial_plan'] = pd.Series(plan_inverse_map, dtype=str) else: k = constants.seats[state]['house'] ideal_pop = state_df.population.sum() / k nx.set_node_attributes(adj_graph, metric_df.T.to_dict()) plan = recursive_tree_part(adj_graph, range(k), ideal_pop, 'population', 0.01) metric_df['initial_plan'] = pd.Series(plan, dtype=str) nx.set_node_attributes(adj_graph, metric_df.T.to_dict()) elections = [ Election(election, { 'Democratic': 'D_' + election, 'Republican': 'R_' + election }) for election in wrappers[state]().election_columns(include_party=False) ] return adj_graph, elections
def build_balanced_k_partition(graph, k, pop_col, pop_target, epsilon): assignment = recursive_tree_part(graph, k, pop_target, pop_col, epsilon) updaters = {'population': Tally('population'), 'cut_edges': cut_edges, 'step_num': step_num, } partition = Partition(graph, assignment=assignment, updaters=updaters) return partition
def test_recursive_tree_part_returns_within_epsilon_of_target_pop(twelve_by_twelve_with_pop): n_districts = 7 # 144/7 ≈ 20.5 nodes/subgraph (1 person/node) ideal_pop = (sum(twelve_by_twelve_with_pop.nodes[node]["pop"] for node in twelve_by_twelve_with_pop)) / n_districts epsilon = 0.05 result = recursive_tree_part(twelve_by_twelve_with_pop, range(n_districts), ideal_pop, "pop", epsilon) partition = Partition(twelve_by_twelve_with_pop, result, updaters={"pop": Tally("pop")}) return all(abs(part_pop - ideal_pop) / ideal_pop < epsilon for part_pop in partition['pop'].values())
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 split_districts(part, factor, pop_target, pop_col, pop_tol): ''' Takes a districting plan and splits each district into smaller ones ''' #must be 0-indexed ass = {} graph = part.graph for d in part.parts: subgraph = graph.subgraph(part.parts[d]) twodistricts = recursive_tree_part(subgraph, range(factor), pop_target, pop_col, pop_tol) for x in subgraph.nodes: ass[x] = d * factor + twodistricts[x] return ass
def create_graph(): graph = nx.grid_graph([k * gn, k * gn]) for e in graph.edges(): graph[e[0]][e[1]]["shared_perim"] = 1 graph.remove_nodes_from([(0, 0), (0, k * gn - 1), (k * gn - 1, 0), (k * gn - 1, k * gn - 1)]) cddict = {x: int(x[0] / gn) for x in graph.nodes()} for n in graph.nodes(): graph.node[n]["population"] = 1 graph.node[n]["part_sum"] = cddict[n] graph.node[n]["last_flipped"] = 0 graph.node[n]["num_flips"] = 0 graph.node[n]["COUNTY1"] = (-1)**(int(n[1] < k * gn / 2)) * int( n[0] / gn) if random.random() < p: graph.node[n]["pink"] = 1 graph.node[n]["purple"] = 0 else: graph.node[n]["pink"] = 0 graph.node[n]["purple"] = 1 if 0 in n or k * gn - 1 in n: graph.node[n]["boundary_node"] = True graph.node[n]["boundary_perim"] = 1 else: graph.node[n]["boundary_node"] = False countydict = recursive_tree_part(graph, range(15), len(graph.nodes()) / 15, "population", .1, 1) for n in graph.nodes(): graph.node[n]["COUNTY2"] = countydict[n] # this part adds queen adjacency # for i in range(gn-1): # for j in range(gn): # if j<(gn-1): # graph.add_edge((i,j),(i+1,j+1)) # graph[(i,j)][(i+1,j+1)]["shared_perim"]=0 # if j >0: # graph.add_edge((i,j),(i+1,j-1)) # graph[(i,j)][(i+1,j-1)]["shared_perim"]=0 return graph, cddict
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 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)
from gerrychain.tree import recursive_tree_part graph = Graph.from_json("./County05.json") df = gpd.read_file("./County05.shp") centroids = df.centroid c_x = centroids.x c_y = centroids.y totpop = 0 for node in graph.nodes(): graph.node[node]["TOTPOP"] = int(graph.node[node]["TOTPOP"]) totpop += graph.node[node]["TOTPOP"] cddict = recursive_tree_part(graph, range(4), totpop / 4, "TOTPOP", .01, 1) pos = {node: (c_x[node], c_y[node]) for node in graph.nodes} def step_num(partition): parent = partition.parent if not parent: return 0 return parent["step_num"] + 1 updaters = { "population": Tally("TOTPOP"), "cut_edges": cut_edges, "step_num": step_num,
partition_2011 = Partition(graph, "2011_PLA_1", updaters) partition_GOV = Partition(graph, "GOV", updaters) partition_TS = Partition(graph, "TS", updaters) partition_REMEDIAL = Partition(graph, "REMEDIAL_P", updaters) partition_CPCT = Partition(graph, "538CPCT__1", updaters) partition_DEM = Partition(graph, "538DEM_PL", updaters) partition_GOP = Partition(graph, "538GOP_PL", updaters) partition_8th = Partition(graph, "8THGRADE_1", updaters) tree_partitions = [] for i in range(5): print(f'Finished {i} tree plan(s)') cddict = recursive_tree_part(graph,range(18),df["TOT_POP"].sum()/18,"TOT_POP", .01,1) tree_partitions.append(Partition(graph, cddict, updaters)) print("The 2011 plan has" , len(partition_2011["cut_edges"]), "cut edges.") print("The GOV plan has" , len(partition_GOV["cut_edges"]), "cut edges.") print("The TS plan has" , len(partition_TS["cut_edges"]), "cut edges.") print("The REMEDIAL plan has" , len(partition_REMEDIAL["cut_edges"]), "cut edges.") print("The 538 Compact plan has" , len(partition_CPCT["cut_edges"]), "cut edges.") print("The 538 DEM plan has" , len(partition_DEM["cut_edges"]), "cut edges.") print("The 538 GOP plan has" , len(partition_GOP["cut_edges"]), "cut edges.") print("The 8th grade plan has" , len(partition_8th["cut_edges"]), "cut edges.") for i in range(5): print(f"Tree plan #{i} has" , len(tree_partitions[i]["cut_edges"]), "cut edges.")
or_updaters = {"population" : Tally(POP_COL, alias="population"), "cut_edges": cut_edges} election_updaters = {election.name: election for election in elections} or_updaters.update(election_updaters) ## Create seed plans and Set up Markov chain print("Creating seed plan") total_pop = sum(df[POP_COL]) ideal_pop = total_pop / NUM_DISTRICTS cddict = recursive_tree_part(graph=graph, parts=range(NUM_DISTRICTS), pop_target=ideal_pop, pop_col=POP_COL, epsilon=EPS) init_partition = Partition(graph, assignment=cddict, updaters=or_updaters) ## 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,
def run_GerryChain_heuristic(G, population_deviation, k, threshold, 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 and minority districts: ", end='') print(min_cut_edges, ",", sep='', end=' ') max_of_minority_districts = -1 all_maps = [] pareto_frontier = [] obj_vals = [] for partition in my_chain: current_cut_edges = sum(G[i][j]['edge_length'] for i, j in partition["cut_edges"]) number_minority_district = 0 for district in range(k): total_pop_district = 0 total_pop_minority = 0 for node in partition.graph: if partition.assignment[node] == district: total_pop_district += G.node[node]["VAP"] total_pop_minority += G.node[node]["BVAP"] #total_pop_minority += G.node[node]["HVAP"] #total_pop_minority += G.node[node]["AMINVAP"] #total_pop_minority += G.node[node]["ASIANVAP"] #total_pop_minority += G.node[node]["NHPIVAP"] if (total_pop_minority > threshold * total_pop_district): number_minority_district += 1 if number_minority_district > max_of_minority_districts: max_of_minority_districts = number_minority_district if current_cut_edges < min_cut_edges: min_cut_edges = current_cut_edges print((current_cut_edges, number_minority_district), ",", sep='', end=' ') obj_vals.append([current_cut_edges, number_minority_district]) all_maps.append( [partition, current_cut_edges, number_minority_district]) print("Best heuristic solution has # cut edges =", min_cut_edges) print("Best heuristic solution has # minority districts =", max_of_minority_districts) all_maps.sort(key=lambda x: x[1]) all_maps.sort(key=lambda x: x[2], reverse=True) pareto_frontier.append(all_maps[0]) least_number_of_cut_edges = all_maps[0][1] for i in range(1, len(all_maps)): if all_maps[i][1] < least_number_of_cut_edges: pareto_frontier.append(all_maps[i]) least_number_of_cut_edges = all_maps[i][1] print("Pareto Frontier: ", pareto_frontier) optimal_maps = [] optimal_cut_edges = [] optimal_minority_districts = [] for plan in pareto_frontier: optimal_maps.append( [[i for i in G.nodes if plan[0].assignment[i] == j] for j in range(k)]) optimal_cut_edges.append(plan[1]) optimal_minority_districts.append(plan[2]) return (optimal_maps, optimal_cut_edges, optimal_minority_districts, obj_vals)
my_updaters = { "population": Tally(pop_col, alias="population"), "cpop": Tally(ccol, alias="cpop"), "cut_edges": cut_edges } election_updaters = {election.name: election for election in elections} my_updaters.update(election_updaters) tot_pop_col = 0 tot_ccol = 0 #for tallying over totpop: for n in graph.nodes(): graph.node[n][pop_col] = int(graph.node[n][pop_col]) tot_pop_col += graph.node[n][pop_col] cddict = recursive_tree_part(graph, range(num_districts), tot_pop_col / num_districts, pop_col, 0.01, 1) starting_partition = Partition(graph, assignment=cddict, updaters=my_updaters) #for tallying over citizen pop: #for n in graph.nodes(): # graph.node[n][ccol] = int(graph.node[n][ccol]) # tot_ccol += graph.node[n][ccol] #cddict = recursive_tree_part(graph,range(num_districts),tot_ccol/num_districts,ccol,0.01,1) #starting_partition = Partition(graph,assignment=cddict,updaters=my_updaters) # ============================================================================= # # starting_partition = GeographicPartition( # graph, # assignment="GOV",
def metamander_around_partition(graph, dual, target_partition, tag, num_dist, secret): updaters = {'population': Tally('population'), 'cut_edges': cut_edges, 'step_num': step_num, } assignment = {} for x in graph.nodes(): color = 0 for block in target_partition.keys(): if x in target_partition[block]: assignment[x] = color color += 1 target_partition = Partition(graph, assignment, updaters=updaters) facefinder.viz(graph, set([]), target_partition.parts) plt.savefig("./plots/large_sample/target_maps/target_map" + tag + ".png", format='png') plt.close() print("made partition") crosses = facefinder.compute_cross_edge(graph, target_partition) k = len(target_partition.parts) dual_crosses = [] for edge in dual.edges: if dual.edges[edge]["original_name"] in crosses: dual_crosses.append(edge) print("making dual distances") dual = facefinder.distance_from_partition(dual, dual_crosses) print('finished making dual distances') if secret: special_faces = assign_special_faces_random(dual) # special_faces = assign_special_faces_sqrt(dual) else: special_faces = assign_special_faces(dual, 2) print('finished assigning special faces') g_sierpinsky = face_sierpinski_mesh(graph, special_faces) print("made metamander") # change from RVAP and UVAP to approprate election data columns for node in g_sierpinsky: g_sierpinsky.nodes[node]['C_X'] = g_sierpinsky.nodes[node]['pos'][0] g_sierpinsky.nodes[node]['C_Y'] = g_sierpinsky.nodes[node]['pos'][1] if 'population' not in g_sierpinsky.nodes[node]: g_sierpinsky.nodes[node]['population'] = 0 if 'EL16G_PR_D' not in g_sierpinsky.nodes[node]: g_sierpinsky.nodes[node]['EL16G_PR_D'] = 0 if 'EL16G_PR_R' not in g_sierpinsky.nodes[node]: g_sierpinsky.nodes[node]['EL16G_PR_R'] = 0 ##Need to add the voting data print("assigning districts to metamander") total_pop = sum( [ g_sierpinsky.nodes[node]['population'] for node in g_sierpinsky]) cddict = recursive_tree_part(graph,range(num_dist),total_pop/num_dist,"population", .01,1) for node in graph.nodes(): graph.nodes[node]['part'] = cddict[node] #sierp_partition = build_trivial_partition(g_sierpinsky) print("assigned districts") plt.figure() nx.draw(g_sierpinsky, pos=nx.get_node_attributes(g_sierpinsky, 'pos'), node_size=1, width=1, cmap=plt.get_cmap('jet')) plt.savefig("./plots/large_sample/sierpinsky_plots/sierpinsky_mesh" + tag + ".png", format='png') plt.close() return g_sierpinsky, k
for i in range(4): graph = graph_list[i] for n in graph.nodes(): graph.node[n]["BVAP"] = int(graph.node[n]["BVAP"]) graph.node[n][vap_list[i]] = int(graph.node[n][vap_list[i]]) graph.node[n]["TOTPOP"] = int(graph.node[n]["TOTPOP"]) totpop[i] += graph.node[n]["TOTPOP"] graph.node[n]["nBVAP"] = graph.node[n][ vap_list[i]] - graph.node[n]["BVAP"] starts = [] for i in range(4): starts.append( recursive_tree_part(graph_list[i], range(num_districts), totpop[i] / num_districts, "TOTPOP", .02, 1)) updater = { "population": updaters.Tally("TOTPOP", alias="population"), "cut_edges": cut_edges, "BVAP": Election("BVAP", { "BVAP": "BVAP", "nBVAP": "nBVAP" }) } initial_partitions = [] proposals = [] compactness_bounds = [] chains = []
#with open("./State_Data/VA_Trimmedj.json", 'w') as outfile: # json.dump(json_graph.adjacency_data(graph), outfile) #graph.to_json("./State_Data/VA_Trimmed.json") graph = Graph.from_json("./State_Data/VA_Trimmed.json") df = gpd.read_file("./State_Data/VA_Trimmed.shp") print("nodes", len(graph.nodes())) print("edges", len(graph.edges())) num_districts = 33 for i in range(100): cddict = recursive_tree_part(graph, range(num_districts), df["TAPERSONS"].sum() / num_districts, "TAPERSONS", .001, 1) df["initial"] = df.index.map(cddict) df.plot(column="initial", cmap="jet") plt.savefig(newdir + "initial.png") plt.close() with open(newdir + "init" + str(i) + ".json", 'w') as jf1: json.dump(cddict, jf1) print("saved Initial", i)
df["VAP"]=pd.to_numeric(df["VAP"]) df["BVAP"]=pd.to_numeric(df["BVAP"]) df["nBVAP"] = df["VAP"]-df["BVAP"] graph = Graph.from_json(graph_path) graph.join(df) for i in range(1): cddict = recursive_tree_part(graph,range(num_districts),df["TOTPOP"].sum()/num_districts,"TOTPOP", .001,1) df["initial"]=df.index.map(cddict) df.plot(column="initial",cmap="jet") plt.savefig(newdir+"initial.png") plt.close() with open(newdir+"init.json", 'w') as jf1: json.dump(cddict, jf1) print("saved Initial") updater = { "population": updaters.Tally("TOTPOP", alias="population"), "cut_edges": cut_edges, "BVAP":Election("BVAP",{"BVAP":"BVAP","nBVAP":"nBVAP"})
def demo(): graph_path = "./Data/PA_VTDALL.json" graph = Graph.from_json(graph_path) k = 18 ep = 0.05 pop_col = "TOT_POP" plot_path = "./Data/VTD_FINAL" unit_df = gpd.read_file(plot_path) unit_col = "GEOID10" division_col = "COUNTYFP10" divisions = unit_df[[division_col, 'geometry']].dissolve(by=division_col, aggfunc='sum') county_dict = pd.Series(unit_df[division_col].values, index=unit_df[unit_col]).to_dict() for v in graph.nodes: graph.nodes[v]['division'] = county_dict[v] graph.nodes[v][unit_col] = v updaters = { "population": Tally("TOT_POP", alias="population"), "cut_edges": cut_edges, } cddict = recursive_tree_part(graph, range(k), unit_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'), 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, './figs/chain_' + str(t) + '.png', geo_id=unit_col) print( "t: ", t, ", num_splits: ", num_splits(part, unit_df, geo_id=unit_col, division_col=division_col), ", cut_length", cut_length(part)) t += 1
my_updaters.update(election_updaters) election_functions = [Election(j, candidates[j]) for j in elections] election_updaters = { election.name: election for election in election_functions } my_updaters.update(election_updaters) #initial partition####################################################### step_Num = 0 total_population = state_gdf[tot_pop].sum() ideal_population = total_population / num_districts if start_map == 'new_seed': start_map = recursive_tree_part(graph, range(num_districts), ideal_population, tot_pop, pop_tol, 3) initial_partition = GeographicPartition(graph=graph, assignment=start_map, updaters=my_updaters) proposal = partial(recom, pop_col=tot_pop, pop_target=ideal_population, epsilon=pop_tol, node_repeats=3) #constraints ############################################ def inclusion(partition): """
totpop = 0 for node in g.nodes(): g.node[node]["TOT_POP"] = int(g.node[node]["TOT_POP"]) totpop += g.node[node]["TOT_POP"] if shape: pos = {node: (c_x[node], c_y[node]) for node in g.nodes} cddicts = [] num_trees = 8 for i in range(num_trees): cddicts.append( recursive_tree_part(g, range(18), totpop / 18, "TOT_POP", .02, 1)) def step_num(partition): parent = partition.parent if not parent: return 0 return parent["step_num"] + 1 def b_nodes_bi(partition): return {x[0] for x in partition["cut_edges"] }.union({x[1] for x in partition["cut_edges"]})
"cut_edges": cut_edges, } elections = [ Election( election_names[i], { "Democratic": election_columns[i][0], "Republican": election_columns[i][1] }, ) for i in range(len(election_names)) ] election_updaters = {election.name: election for election in elections} myupdaters.update(election_updaters) #initial partition ass = recursive_tree_part(graph, range(k), total_population / k, pop_col, pop_tol) initial_partition = Partition(graph, ass, myupdaters) dev = max([ np.abs(initial_partition["population"][d] - pop_target) for d in initial_partition.parts ]) print(" Using initial", k, "districts with population deviation = ", 100 * dev / pop_target, "% of ideal.") #chain myconstraints = [ constraints.within_percent_of_ideal_population(initial_partition, pop_tol) ] chain = MarkovChain(proposal=myproposal, constraints=myconstraints,
another_dists = np.add(0.1 * geo_dists, partisan) # In[56]: another_dists # In[22]: cddicts = [] num_cong_dists = 18 num_trees = 0 for i in range(num_trees): cddicts.append( recursive_tree_part(g, range(num_cong_dists), totpop / num_cong_dists, "TOT_POP", .02, 1)) ideal_population = totpop / num_cong_dists proposal = propose_random_flip def cut_length(partition): return len(partition["cut_edges"]) num_flips = 5 num_flip_steps = 1000 def step_num(partition):
graph.add_data(df, columns=new_cols) # In[9]: graph.nodes[1]['CVAP'] # In[5]: # INITIAL PARTITION ASSIGNMENT USING RECURSIVE TREE PARTITION starts = [] for i in range(1): starts.append( recursive_tree_part(graph, range(num_districts), df['CVAP'].sum() / num_districts, "CVAP", .001, 1)) #starts.append(recursive_tree_part(graph,range(num_districts),df['TOTPOP'].sum()/num_districts, "TOTPOP", .001, 1)) # In[6]: updater = { "population": updaters.Tally("TOTPOP", alias="population"), "cut_edges": cut_edges, "BVAP": Election("BVAP", { "BVAP": "BVAP", "nBVAP": "nBVAP" }), "BCVAP": Election("BCVAP", { "BCVAP": "BCVAP", "nBCVAP": "nBCVAP" })
"VAP": Tally(VAP, alias="VAP"), "cpop": Tally(ccol, alias="cpop"), "cut_edges": cut_edges } election_updaters = {election.name: election for election in elections} my_updaters.update(election_updaters) tot_pop_col = 0 tot_ccol = 0 tot_VAP = 0 #for tallying over VAP: for n in graph.nodes(): graph.node[n][VAP] = int(graph.node[n][VAP]) tot_VAP += graph.node[n][VAP] cddict = recursive_tree_part(graph, range(num_districts), tot_VAP / num_districts, VAP, 0.01, 1) starting_partition = Partition(graph, assignment=cddict, updaters=my_updaters) #------------------------------------------------------------------------------------------- #CHAIN FOR TOTPOP proposal = partial(recom, pop_col=VAP, pop_target=tot_VAP / num_districts, epsilon=0.02, node_repeats=1) compactness_bound = constraints.UpperBound( lambda p: len(p["cut_edges"]), 2 * len(starting_partition["cut_edges"]))
elections = [ Election( election_names[i], {"Democratic": election_columns[i][0], "Republican": election_columns[i][1]}, ) for i in range(len(election_names)) ] election_updaters = {election.name: election for election in elections} myupdaters.update(election_updaters) #initial partition print("Creating seed with", k, "districts.") dev = pop_tol*pop_target + 1 while dev > pop_tol*pop_target: print(".", end="") initial_ass = recursive_tree_part(graph, range(k), pop_target, pop_col, pop_tol, node_repeats=10) initial_partition = Partition(graph, initial_ass, myupdaters) dev = max([np.abs(initial_partition["population"][d] - pop_target) for d in initial_partition.parts]) dev = max([np.abs(initial_partition["population"][d] - pop_target) for d in initial_partition.parts]) print(" Using initial", k, "districts with population deviation = ", 100*dev/pop_target, "% of ideal.") #chain compactness_bound = constraints.UpperBound( lambda p: len(p["cut_edges"]), 2*len(initial_partition["cut_edges"]) ) myconstraints = [ constraints.within_percent_of_ideal_population(initial_partition, pop_tol), compactness_bound ] chain = MarkovChain(
mo_updaters.update(election_updaters) ## ## ## ## ## ## ## ## ## ## ## ## Initial partition ## ## ## ## ## ## ## ## ## ## ## print("Creating seed plan") ################################################################## ######## ! if using a random map as the initial partition ################################################################## # NUM_DISTRICTS=34 # EPS=0.05 total_pop = sum(dat[POP_COL]) ideal_pop = total_pop / NUM_DISTRICTS cddict = recursive_tree_part(graph=graph, parts=range(NUM_DISTRICTS), pop_target=ideal_pop, pop_col=POP_COL, epsilon=EPS) init_partition = GeographicPartition(graph, assignment=cddict, updaters=mo_updaters) # init_partition["USSEN16"].efficiency_gap() #PRES EG = -0.08, USSEN EG = -0.18 ################################################################## ######## ! if using the enacted state senate map as the initial partition ################################################################## # init_partition = GeographicPartition(graph, assignment="SLDUST", updaters=mo_updaters) # init_partition["USSEN16"].efficiency_gap() # ideal_pop = sum(init_partition['population'].values()) / len(init_partition) # # show stuff about the initial partition # init_partition.graph # init_partition.graph.nodes[0] # init_partition['population']
race_con(racial_vap_ref, 3)) nvap_con = constraints.LowerBound( lambda p: race_con(p["racial_demographics"], 4), race_con(racial_vap_ref, 4)) pvap_con = constraints.LowerBound( lambda p: race_con(p["racial_demographics"], 5), race_con(racial_vap_ref, 5)) racial_bound = constraints.Validator( [bvap_con, hvap_con, avap_con, nvap_con, pvap_con]) if old_dist != num_dist: # do random initial partition optimization recursive_part = recursive_tree_part(graph, range(num_dist), pop_target=pop / num_dist, pop_col=pop_col, epsilon=0.05, node_repeats=3) random_init_partition = GeographicPartition(graph, recursive_part, updaters) # Racial backsliding test racial_breakdown = random_init_partition["racial_demographics"] if not (backsliding_pass(racial_vap_ref, racial_breakdown)): chain_racial_requirements = MarkovChain( proposal=proposal, constraints=[ constraints.within_percent_of_ideal_population( random_init_partition, 0.05) ],
shape = True nlist = list(g.nodes()) n = len(nlist) totpop = 0 for node in g.nodes(): g.node[node]["TOTPOP"] = int(g.node[node]["TOTPOP"]) totpop += g.node[node]["TOTPOP"] pos = nx.kamada_kawai_layout(g) if shape: pos = {node: (c_x[node], c_y[node]) for node in g.nodes} cddict1 = recursive_tree_part(g, range(4), totpop / 4, "TOTPOP", .01, 1) cddict2 = recursive_tree_part(g, range(4), totpop / 4, "TOTPOP", .01, 1) def step_num(partition): parent = partition.parent if not parent: return 0 return parent["step_num"] + 1 def b_nodes_bi(partition): return {x[0] for x in partition["cut_edges"] }.union({x[1]
betas = [] ts = [] myupdaters = { 'population': Tally('TOTPOP', alias="population"), 'cut_edges': cut_edges, 'step_num': step_num, } runlist = [0] partdict = {r: [] for r in runlist} allparts = [] #run annealing flip for run in runlist: initial_ass = recursive_tree_part(graph, range(6), totpop / 6, "TOTPOP", .01, 1) initial_partition = Partition(graph, assignment=initial_ass, updaters=myupdaters) popbound = within_percent_of_ideal_population(initial_partition, pop_tol) ideal_population = totpop / 6 print("Dumping seed", run) pickle.dump(initial_ass, open("oneseed" + str(run), "wb")) #make flip chain exp_chain = MarkovChain(propose_random_flip, constraints=[single_flip_contiguous, popbound], accept=annealing_cut_accept2, initial_state=initial_partition, total_steps=STEPS)