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)
graph = Graph.from_file(path_to_shapefile) #graph = Graph.from_json(path_to_shapefile) #graph = gpd.read_file(path_to_shapefile) # ---- Updaters & Elections ----- updaters = { "population": updaters.Tally(pop_col, alias="population"), "cut_edges": cut_edges, "BVAP": updaters.Tally(BVAP_col, alias="BVAP"), "HVAP": updaters.Tally(HVAP_col, alias="HVAP"), "AVAP": updaters.Tally(AVAP_col, alias="AVAP"), "NVAP": updaters.Tally(Native_col, alias="NVAP"), "PVAP": updaters.Tally(Pacific_col, alias="PVAP"), "VAP": updaters.Tally(VAP_col, alias="VAP"), "county_splits": county_splits("county_splits", county_assignment_col) } num_elections = len(election_names) elections = [ Election( election_names[i], { "Dem": election_columns[i][0], "Rep": election_columns[i][1] }, ) for i in range(num_elections) ] election_updaters = {election.name: election for election in elections}
## ## ## ## ## ## ## ## ## ## ## ## 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 plan_evaluation(partition): graph = partition.graph # Naming constants county_column = "COUNTY" municipality_column = "TOWN" # Contiguity split_districts = [] for district in partition.parts.keys(): if district != -1: part_contiguous = nx.is_connected(partition.subgraphs[district]) if not part_contiguous: split_districts.append(district) contiguity = (len(split_districts) == 0) # Calculate cut edges cut_edges = updaters.cut_edges(partition) # Polsby Popper try: polsbypopper = [ v for _k, v in metrics.polsby_popper(partition).items() ] polsbypopper_stats = { 'max': max(polsbypopper), 'min': min(polsbypopper), 'mean': statistics.mean(polsbypopper), 'median': statistics.median(polsbypopper) } if len(polsbypopper) > 1: polsbypopper_stats['variance'] = statistics.variance(polsbypopper) except: polsbypopper = [] polsbypopper_stats = "Polsby Popper unavailable for this geometry." # county splits try: county_splits = updaters.county_splits("county_splits", county_column)(partition) county_response = {} counties = set([graph.nodes[n][county_column] for n in graph.nodes]) county_response['num_counties'] = len(counties) try: county_partition = GeographicPartition( graph, county_column, {"population": updaters.Tally('TOTPOP', alias="population")}) county_pop_dict = { c: county_partition.population[c] for c in counties } county_response['population'] = county_pop_dict except KeyError: county_response['population'] = -1 split_list = {} splits = 0 num_split = 0 for c in counties: s = county_splits[c].contains # this is caused by a bug in some states in gerrychain I think if -1 in s: s.remove(-1) if len(s) > 1: num_split += 1 split_list[c] = list(s) splits += len(s) - 1 county_response['splits'] = splits county_response['split_list'] = split_list except: county_response = -1 # municipality splits try: municipality_splits = updaters.county_splits( "muni_splits", municipality_column)(partition) muni_response = {} munis = set([graph.nodes[n][municipality_column] for n in graph.nodes]) muni_response['num_counties'] = len(munis) try: muni_partition = GeographicPartition( graph, municipality_column, {"population": updaters.Tally('TOTPOP', alias="population")}) muni_pop_dict = {m: muni_partition.population[m] for m in munis} muni_response['population'] = muni_pop_dict muni_response['num_counties'] = len(munis) except KeyError: muni_response['population'] = -1 split_list = {} splits = 0 num_split = 0 for m in munis: s = municipality_splits[m].contains # this is caused by a bug in some states in gerrychain I think if -1 in s: s.remove(-1) if len(s) > 1: num_split += 1 split_list[m] = list(s) splits += len(s) - 1 muni_response['splits'] = splits muni_response['split_list'] = split_list except: muni_response = -1 # Build Response dictionary response = { 'cut_edges': len(cut_edges), 'contiguity': contiguity, 'split': split_districts, 'polsbypopper': polsbypopper_stats, 'pp_scores': polsbypopper, 'num_units': len(graph.nodes), 'counties': county_response, 'municipalities': muni_response } return response
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)
def run_simple(graph, num_samples = 80000, wp = 3000, wi = 2.5, wc = 0.4, wm = 800, get_parts = 5): election = Election( "2014 Senate", {"Democratic": "sen_blue", "Republican": "sen_red"}, alias="2014_Senate" ) initial_partition = Partition( graph, assignment="2014_CD", 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"), } ) def vra_validator(part): if(vra_district_requirement(part, 2, [0.4, 0.335]) > 0): return False return True districts_within_tolerance_2 = lambda part : districts_within_tolerance(part, 'population', 0.12) is_valid = Validator([single_flip_contiguous, districts_within_tolerance_2, vra_validator ]) def accept(partition, counter): if(counter < 40000): beta = 0 elif(counter < 60000): beta = (counter - 40000) /(60000-40000) else: beta = 1 return(metro_scoring_prob(partition, beta, wp, wi, wc, wm)) chain = MarkovChainAnneal( proposal=propose_random_flip, is_valid=is_valid, accept=accept, initial_state=initial_partition, total_steps= num_samples * 100, ) # going to show 5 partitions from this sample part_con = max(1, num_samples / get_parts) efficiency_gaps = [] wins = [] voting_percents = [] sample_parts = [] tbefore = time.time() 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")) voting_percents.append(partition["2014_Senate"].percents("Democratic")) num_s = len(wins) if(num_s % part_con) == 0: sample_parts.append(partition) if(num_s> num_samples): break if(num_s % 1000 == 0): tnext = time.time() print("It took %i time to get 1000 samples" % (tnext - tbefore)) tbefore = time.time() return(efficiency_gaps, wins, voting_percents, sample_parts)