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 initial_partition(disc): updaters = { 'population': Tally('population'), 'base': new_base, 'b_nodes': b_nodes_bi, 'cut_edges': cut_edges, "boundary": bnodes_p, 'step_num': step_num, 'geom': geom_wait, } assignment = {} for x in disc.nodes(): if x[0] > 0: assignment[x] = 1 else: assignment[x] = -1 #b_nodes = {(x[0], partition.assignment[x[1]]) for x in partition["cut_edges"]}.union({(x[1], partition.assignment[x[0]]) for x in partition["cut_edges"]}) partition = Partition(disc, assignment, updaters=updaters) return partition
def buildPartition(graph, mean): """ The function build 2 partition based on x coordinate value Parameters: graph (Graph): The given graph represent state information mean (int): the value to determine partition Returns: Partition: the partitions of the graph based on mean value """ assignment = {} # assign node into different partition based on x coordinate for x in graph.node(): if graph.node[x]['C_X'] < mean: assignment[x] = -1 else: assignment[x] = 1 updaters = { 'population': Tally('population'), "boundary": bnodes_p, 'cut_edges': cut_edges, 'step_num': step_num, 'b_nodes': b_nodes_bi, 'base': new_base, 'geom': geom_wait, } grid_partition = Partition(graph, assignment=assignment, updaters=updaters) return grid_partition
def metamander_around_partition(graph, dual, target_partition, tag): 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) plt.figure() viz(graph, set([]), target_partition.parts) plt.savefig("./plots/target_map" + tag + ".png", format = 'png') plt.close() print("made partition") crosses = 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 = distance_from_partition(dual, dual_crosses) print('finished making dual distances') 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 total_pop = sum( [ g_sierpinsky.nodes[node]['population'] for node in g_sierpinsky]) #sierp_partition = build_trivial_partition(g_sierpinsky) 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/sierpinsky_mesh.png", format='png') plt.close() left_mander, right_mander = produce_sample(g_sierpinsky, k , tag)
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 main(config_data, id): try: timeBeg = time.time() print('Experiment', id, 'has begun') # Save configuration into global variable global config config = config_data graph = Graph.from_json(config['INPUT_GRAPH_FILENAME']) # List of districts in original graph parts = list( set([ graph.nodes[node][config['ASSIGN_COL']] for node in graph.nodes() ])) # Ideal population of districts ideal_pop = sum( [graph.nodes[node][config['POP_COL']] for node in graph.nodes()]) / len(parts) election = Election(config['ELECTION_NAME'], { 'PartyA': config['PARTY_A_COL'], 'PartyB': config['PARTY_B_COL'] }) updaters = { 'population': Tally(config['POP_COL']), 'cut_edges': cut_edges, config['ELECTION_NAME']: election } partDict = recursive_tree_part(graph, parts, ideal_pop, config['POP_COL'], config['EPSILON'], config['NODE_REPEATS']) for node in graph.nodes(): graph.nodes[node][config['ASSIGN_COL']] = partDict[node] part = Partition(graph=graph, assignment=config['ASSIGN_COL'], updaters=updaters) for len_ in config['RUN_LENGTHS']: for num in range(config['RUNS_PER_LEN']): run_chain(part, config['CHAIN_TYPE'], len_, ideal_pop, '{}_{}_{}_{}'.format(config['TAG'], id, len_, num)) print('Experiment {} completed in {} seconds'.format( id, time.time() - timeBeg)) except Exception as e: # Print notification if any experiment fails to complete track = traceback.format_exc() print(track) print('Experiment {} failed to complete after {:.2f} seconds'.format( id, time.time() - timeBeg))
def test_tally_multiple_columns(graph_with_d_and_r_cols): graph = graph_with_d_and_r_cols updaters = {"total": Tally(["D", "R"], alias="total")} assignment = {i: 1 if i in range(4) else 2 for i in range(9)} partition = Partition(graph, assignment, updaters) expected_total_in_district_one = sum( graph.nodes[i]["D"] + graph.nodes[i]["R"] for i in range(4)) assert partition["total"][1] == expected_total_in_district_one
def test_tally_multiple_columns(graph_with_d_and_r_cols): graph = graph_with_d_and_r_cols updaters = {'total': Tally(['D', 'R'], alias='total')} assignment = {i: 1 if i in range(4) else 2 for i in range(9)} partition = Partition(graph, assignment, updaters) expected_total_in_district_one = sum( graph.nodes[i]['D'] + graph.nodes[i]['R'] for i in range(4)) assert partition['total'][1] == expected_total_in_district_one
def test_recursive_seed_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.1 result = recursive_seed_part(twelve_by_twelve_with_pop, range(n_districts), ideal_pop, "pop", epsilon, n=5, ceil=None) 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 build_trivial_partition(graph): assignment = {} for y in graph.nodes(): assignment[y] = 1 first_node = list(graph.nodes())[0] assignment[first_node] = -1 updaters = {'population': Tally('population'), 'cut_edges': cut_edges, 'step_num': step_num, } partition = Partition(graph, assignment=assignment, updaters=updaters) return partition
def build_partition_meta(graph, mean): assignment = {} for y in graph.nodes(): if graph.nodes[y]['C_Y'] < mean: assignment[y] = -1 else: assignment[y] = 1 updaters = {'population': Tally('population'), 'cut_edges': cut_edges, 'step_num': step_num, } partition = Partition(graph, assignment=assignment, updaters=updaters) print("cut edges are", partition["cut_edges"]) return partition
class GeographicPartition(Partition): """A :class:`Partition` with areas, perimeters, and boundary information included. These additional data allow you to compute compactness scores like `Polsby-Popper <https://en.wikipedia.org/wiki/Polsby-Popper_Test>`_. """ default_updaters = { "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, }
def build_balanced_partition(graph, pop_col, pop_target, epsilon): block = my_mst_bipartition_tree_random(graph, pop_col, pop_target, epsilon) assignment = {} for y in graph.nodes(): if y in block: assignment[y] = 1 else: assignment[y] = -1 updaters = {'population': Tally('population'), 'cut_edges': cut_edges, 'step_num': step_num, } partition = Partition(graph, assignment=assignment, updaters=updaters) return partition
def test_Partition_can_update_stats(): graph = networkx.complete_graph(3) assignment = {0: 1, 1: 1, 2: 2} graph.nodes[0]['stat'] = 1 graph.nodes[1]['stat'] = 2 graph.nodes[2]['stat'] = 3 updaters = {'total_stat': Tally('stat', alias='total_stat')} partition = Partition(graph, assignment, updaters) assert partition['total_stat'][2] == 3 flip = {1: 2} new_partition = partition.merge(flip) assert new_partition['total_stat'][2] == 5
def test_Partition_can_update_stats(): graph = networkx.complete_graph(3) assignment = {0: 1, 1: 1, 2: 2} graph.nodes[0]["stat"] = 1 graph.nodes[1]["stat"] = 2 graph.nodes[2]["stat"] = 3 updaters = {"total_stat": Tally("stat", alias="total_stat")} partition = Partition(graph, assignment, updaters) assert partition["total_stat"][2] == 3 flip = {1: 2} new_partition = partition.flip(flip) assert new_partition["total_stat"][2] == 5
def build_partition(graph): partition_dict = {} partition_block = my_mst_kpartition_tree_random(graph, pop_col="population", pop_target=0, epsilon=0.05, num_blocks=8, node_repeats=1, spanning_tree=None, choice=random.choice) for n in graph.nodes: for x in range(len(partition_block)): if n in partition_block[x]: partition_dict[n] = x updaters = {'population': Tally('population'), 'cut_edges': cut_edges, 'step_num': step_num, 'base': new_base, } grid_partition = Partition(graph, assignment=partition_dict, updaters=updaters) return grid_partition, partition_dict
def partition_with_pop(graph_with_pop): return Partition( graph_with_pop, { 0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 1, 6: 1, 7: 1, 8: 1 }, updaters={ "pop": Tally("pop"), "cut_edges": cut_edges }, )
def buildPartition(graph, mean): # horizontal = [] assignment = {} for x in graph.node(): if graph.node[x]['C_X'] < mean: assignment[x] = -1 else: assignment[x] = 1 updaters = { 'population': Tally('population'), "boundary": bnodes_p, 'cut_edges': cut_edges, 'step_num': step_num, 'b_nodes': b_nodes_bi, 'base': new_base, 'geom': geom_wait, } grid_partition = Partition(graph, assignment=assignment, updaters=updaters) return grid_partition
class GeographicPartition(Partition): """A :class:`Partition` with areas, perimeters, and boundary information included. These additional data allow you to compute compactness scores like `Polsby-Popper_ <https://en.wikipedia.org/wiki/Polsby-Popper_Test>`. """ default_updaters = { "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, } @classmethod def from_file(cls, filename, assignment, updaters, columns=None): """Create a :class:`GeographicPartition` from an ESRI Shapefile, a GeoPackage, a GeoJSON file, or any other file that the `fiona` library can handle. """ graph = Graph.from_file(filename, columns) cls(graph, assignment, updaters)
graph = nx.relabel_nodes(graph, df[uid]) elections = [ Election("PRES16", { "Democratic": "PRES16D", "Republican": "PRES16R" }), Election("SEN16", { "Democratic": "SEN16D", "Republican": "SEN16R" }) ] #my_updaters = {"population" : updaters.Tally("TOTPOP", alias="population")} 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)
# open enacted map graph = Graph.from_file( "/Users/hopecj/projects/gerryspam/MO/dat/final_prec/prec_labeled.shp") elections = [ Election("USSEN16", { "Dem": "G16USSDKAN", "Rep": "G16USSRBLU" }), Election("PRES16", { "Dem": "G16PREDCLI", "Rep": "G16PRERTRU" }) ] mo_updaters = { "population": Tally("POP10", alias="population"), "cut_edges": cut_edges } election_updaters = {election.name: election for election in elections} mo_updaters.update(election_updaters) sen_part = Partition(graph, assignment="SLDUST", updaters=mo_updaters) sen_part["PRES16"].efficiency_gap() sen_part.plot(cmap="tab20") plt.show() # show the state senate map cong_part = Partition(graph, assignment="SLDLST", updaters=mo_updaters) # load parts (aka district maps) from gerrychain # "assignment" = mapping of node IDs to district IDs sen_parts = np.load( "/Users/hopecj/projects/gerryspam/MO/res/MO_state_senate_100000_0.05_parts.p"
if not parent: return 0 return parent["step_num"] + 1 bnodes = [x for x in graph.nodes() if graph.nodes[x]["boundary_node"] ==1] def bnodes_p(partition): return [x for x in graph.nodes() if graph.nodes[x]["boundary_node"] ==1] updaters = {'population': Tally('population'), "boundary":bnodes_p, 'cut_edges': cut_edges, 'step_num': step_num, 'b_nodes':b_nodes_bi, 'base':new_base, 'geom':geom_wait, #"Pink-Purple": Election("Pink-Purple", {"Pink":"pink","Purple":"purple"}) } #########BUILD PARTITION
# ######### BUILD ASSIGNMENT cddict = {x: int(x[0] / gn) for x in graph.nodes()} pos = {x: x for x in graph.nodes()} # ### CONFIGURE UPDATERS def step_num(partition): parent = partition.parent if not parent: return 0 return parent["step_num"] + 1 updaters = { "population": Tally("population"), "cut_edges": cut_edges, "step_num": step_num, # "Pink-Purple": Election("Pink-Purple", {"Pink":"pink","Purple":"purple"}) } # ########BUILD FIRST PARTITION grid_partition = Partition(graph, assignment=cddict, updaters=updaters) # ADD CONSTRAINTS popbound = within_percent_of_ideal_population(grid_partition, 0.1) # ########Setup Proposal ideal_population = sum( grid_partition["population"].values()) / len(grid_partition)
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
return parent["step_num"] + 1 bnodes = [ x for x in graph.nodes() if graph.nodes[x]["boundary_node"] == 1 ] def bnodes_p(partition): return [ x for x in graph.nodes() if graph.nodes[x]["boundary_node"] == 1 ] updaters = { 'population': Tally('population'), "boundary": bnodes_p, 'cut_edges': cut_edges, 'step_num': step_num, 'b_nodes': b_nodes_bi, 'base': new_base, 'geom': geom_wait, #"Pink-Purple": Election("Pink-Purple", {"Pink":"pink","Purple":"purple"}) } #########BUILD PARTITION grid_partition = Partition(graph, assignment=cddict, updaters=updaters)
return total ## ## ## ## ## ## ## ## ## ## ## ## creating an initial partition ## ## ## ## ## ## ## ## ## ## ## print("Reading in Data/Graph") dat_path = "/Users/hopecj/projects/gerryspam/MO/dat/final_prec/prec_labeled.shp" dat = gpd.read_file(dat_path) list(dat.columns) dat['SLDUST'].nunique() dat['SLDLST'].nunique() graph = Graph.from_file(dat_path) mo_updaters = {"population" : Tally(POP_COL, alias="population"), "cut_edges": cut_edges, "county_splits": county_splits("county_splits", "COUNTYFP"), "num_vra_districts": num_vra_districts, "polsby_popper": polsby_popper} elections = [Election("USSEN16", {"Dem": "G16USSDKAN", "Rep": "G16USSRBLU"}), Election("PRES16", {"Dem": "G16PREDCLI", "Rep": "G16PRERTRU"})] election_updaters = {election.name: election for election in elections} mo_updaters.update(election_updaters) ## ## ## ## ## ## ## ## ## ## ## ## Initial partition ## ## ## ## ## ## ## ## ## ## ## print("Creating seed plan")
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 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
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"]}) updaters = { "population": Tally("TOTPOP"), "cut_edges": cut_edges, "step_num": step_num, 'b_nodes': b_nodes_bi } Part1 = Partition(g, cddict1, updaters) Part2 = Partition(g, cddict2, updaters) initial_infection = len(Part1['b_nodes']) spontaneous = 0.01 recover = .01 spread = .05 reinfect = False
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)