Commit 9e7d47e3 by Garrett Johnson

Merge branch 'master' of mit.cs.uchicago.edu:ajfriedman/election_district_drawing

parents 562daf7d ed56d080
algorithms directory:
algorithms.py contains all the functions for constructing district plans by utilizing
the efficiency gap
drawing.py (must be run using Python2) creates a basemap of the United States and maps color-
coded tracts (the color corresponding to their district) onto the basemap using Networkx
reading_shapes directory:
get_combined.py contains functions to convert shapefiles of census tracts, determine which tracts
are connected to each other, and analyze demographic data to estimate the number of Republicans and Democrats in each district
location_api.py uses the GPS coordinates of census tracts to determine which state they are in
and sorts them accordingly
and sorts them accordingly, using the LocationIQ API
state_set_json_files contains the partially completed tracts as dictionaries created by
location_api.py
state_tracts_full_json_files contains the completed tract dictionaries created by get_combined.py
......
......@@ -85,8 +85,6 @@ def calculate_efficiency_gap_from_list(total_votes, rep_votes, dem_votes, tracts
efficiency_gap = (wasted_dvotes - wasted_rvotes) / total_votes
return efficiency_gap
def calculate_efficiency_gap_from_dict(district_plan):
'''
Given a districting plan for a state, return the efficiency gap for the plan.
......@@ -253,46 +251,26 @@ def draw_districts(tracts, num_districts, starting_tract, percent_of_people, tot
return districts_dict
# def find_0_1_2_3_greater4(tracts, num_districts, initial_percent_of_people, difference):
# percent_of_people = initial_percent_of_people
# count_passed = True
# percent_greater_3 = False
# percent_3 = False
# percent_2 = False
# percent_1 = False
# percent_0 = False
# while count_passed and percent_of_people <= 100:
# count = 0
# pc_of_people = percent_of_people / 100
# count_passed = 0
# starting_tract_dict = {}
# for starting_tract in tracts:
# count += 1
# print(count, starting_tract)
# districts_dict = draw_districts(tracts, num_districts, starting_tract, pc_of_people)
# if districts_dict:
# count_passed += 1
# if not count_passed > 4:
# starting_tract_dict[starting_tract] = districts_dict
# # Uses for one_nine
# if count_passed > 4:
# percent_greater_3 = percent_of_people
# if not (count_passed - 3):
# percent_3 = percent_of_people
# if not (count_passed - 2):
# percent_2 = percent_of_people
# if not (count_passed - 1):
# percent_1 = percent_of_people
# percent_of_people += difference
# if not count_passed:
# percent_of_people -= difference
# percent_0 = percent_of_people
# return percent_0, percent_1, percent_2, percent_3, percent_greater_3
def find_0_1_2_3_greater4(tracts, num_districts, initial_percent_of_people, difference, total_population):
'''
Purpose
Inputs:
tracts:
num_districts:
initial_percent_of_people:
difference:
total_population:
Returns:
1
2
3
4
5
'''
percent_of_people = initial_percent_of_people
count_passed = True
percent_greater_3 = False
......@@ -302,15 +280,12 @@ def find_0_1_2_3_greater4(tracts, num_districts, initial_percent_of_people, diff
count_passed
while percent_of_people <= 100:
#print(percent_of_people)
count = 0
pc_of_people = percent_of_people / 100
count_passed = 0
#print(count_passed)
starting_tract_dict = {}
for starting_tract in tracts:
count += 1
#print(count, starting_tract)
districts_dict = draw_districts(tracts, num_districts, starting_tract, pc_of_people, total_population)
if districts_dict:
count_passed += 1
......@@ -318,10 +293,6 @@ def find_0_1_2_3_greater4(tracts, num_districts, initial_percent_of_people, diff
passed_count = count_passed
passed_percent_of_people = percent_of_people
passed_district_id = starting_tract
# if count_passed > 1:
# starting_tract_dict[starting_tract] = districts_dict
# Uses for one_nine
if not count_passed:
return (percent_of_people, passed_percent_of_people, passed_count, passed_district, passed_district_id)
......@@ -332,6 +303,24 @@ def find_0_1_2_3_greater4(tracts, num_districts, initial_percent_of_people, diff
def countdown(tracts, num_districts, initial_percent_of_people, difference, total_population):
'''
Purpose
Inputs:
tracts:
num_districts:
initial_percent_of_people:
difference:
total_population:
Returns:
1
2
3
4
5
'''
percent_of_people = initial_percent_of_people
count_passed = False
percent_greater_3 = False
......@@ -361,40 +350,27 @@ def countdown(tracts, num_districts, initial_percent_of_people, difference, tota
percent_of_people -= difference
# if count_passed > 1:
# starting_tract_dict[starting_tract] = districts_dict
# Uses for one_nine
return (percent_of_people, passed_percent_of_people, passed_count, passed_district, passed_district_id)
# return (percent_of_people + difference, passed_percent_of_people, passed_count, passed_district, passed_district)
# def one_nine(tracts, num_districts, low_num, high_num, number_produce):
# percent_of_people = low_num
# count_passed = number_produce
# percent_num_produce = False
# while count_passed >= number_produce and percent_of_people <= high_num:
# pc_of_people = percent_of_people / 100
# count_passed = 0
# starting_tract_dict = {}
# for starting_tract in tracts:
# districts_dict = draw_districts(tracts, num_districts, starting_tract, pc_of_people)
# if districts_dict:
# count_passed += 1
# if not count_passed > number_produce:
# starting_tract_dict[starting_tract] = districts_dict
# if not (count_passed - number_produce):
# percent_num_produce = (percent_of_people, starting_tract_dict, )
# percent_of_people += 1
def percents_countdown(state_tract, num_districts, initial_percent_of_people, total_population):
'''
Purpose
# return percent_num_produce
Inputs:
tracts:
num_districts:
initial_percent_of_people:
difference:
total_population:
Returns:
1
2
def percents_countdown(state_tract, num_districts, initial_percent_of_people, total_population):
'''
percent_of_people = initial_percent_of_people
count_passed = 0
percent_greater_3 = False
......@@ -408,14 +384,11 @@ def percents_countdown(state_tract, num_districts, initial_percent_of_people, to
count = 0
pc_of_people = percent_of_people / 100
count_passed = 0
#print(count_passed)
starting_tract_dict = {}
for starting_tract in state_tract:
print(starting_tract)
count += 1
#print(count, starting_tract)
districts_dict = draw_districts(state_tract, num_districts, starting_tract, pc_of_people, total_population)
# print(districts_dict)
if districts_dict:
count_passed += 1
passed_district = districts_dict
......@@ -426,25 +399,25 @@ def percents_countdown(state_tract, num_districts, initial_percent_of_people, to
percent_of_people -= difference
# if count_passed > 1:
# starting_tract_dict[starting_tract] = districts_dict
# Uses for one_nine
return passed_district, passed_district_id
# run = countdown(state_tract, num_districts, initial_percent_of_people, 10, total_population)
# passed_count = run[2]
# if not passed_count:
# return "FAILURE"
# percent_of_people = run[0]
# passed_percent_of_people = run[1]
# passed_count = run[2]
# passed_district = run[3]
# passed_district_id = run[4]
def demo_countdown(tracts, num_districts, initial_percent_of_people, difference, total_population):
'''
Purpose
# return passed_district, passed_district_id
Inputs:
tracts:
num_districts:
initial_percent_of_people:
difference:
total_population:
def demo_countdown(tracts, num_districts, initial_percent_of_people, difference, total_population):
Returns:
1
2
'''
percent_of_people = initial_percent_of_people
count_passed = 0
percent_greater_3 = False
......@@ -481,31 +454,21 @@ def demo_countdown(tracts, num_districts, initial_percent_of_people, difference,
# Uses for one_nine
return passed_district, passed_district_id
# return (percent_of_people + difference, passed_percent_of_people, passed_count, passed_district, passed_district)
# def one_nine(tracts, num_districts, low_num, high_num, number_produce):
# percent_of_people = low_num
# count_passed = number_produce
# percent_num_produce = False
# while count_passed >= number_produce and percent_of_people <= high_num:
def demo_perecent(state_str, initial_percent_of_people, total_population):
'''
Purpose
# pc_of_people = percent_of_people / 100
# count_passed = 0
# starting_tract_dict = {}
# for starting_tract in tracts:
# districts_dict = draw_districts(tracts, num_districts, starting_tract, pc_of_people)
# if districts_dict:
# count_passed += 1
# if not count_passed > number_produce:
# starting_tract_dict[starting_tract] = districts_dict
# if not (count_passed - number_produce):
Inputs:
state_str
initial_percent_of_people
total_population
Returns:
1
2
def demo_perecent(state_str, initial_percent_of_people, total_population):
'''
state_tract, district_num = set_tracts(state=state_str)
run = demo_countdown(state_tract, district_num, initial_percent_of_people, 10, total_population)
passed_district = run[0]
......@@ -518,8 +481,23 @@ def demo_perecent(state_str, initial_percent_of_people, total_population):
def percents(tracts, num_districts, initial_percent_of_people):
'''
Purpose
Inputs:
tracts
num_districts
initial_percent_of_people
Returns:
1
2
3
4
'''
run = find_0_1_2_3_greater4(tracts, num_districts, initial_percent_of_people, 10, total_population)
#print(run[1])
passed_count = run[2]
while not passed_count:
new_percent_of_people = initial_percent_of_people - 10
......@@ -535,211 +513,465 @@ def percents(tracts, num_districts, initial_percent_of_people):
return passed_count, passed_percent_of_people, passed_district, passed_district_id
def get_unused_set(state_tracts, used_tracts):
'''
Reason
Inputs:
state_tracts: a dictionary of dictionaries containing the data on all tracts in the state
used_tracts: a dictionary containing used geoid ids, a string and its district placeement, a interger
Returns: a set of strings, unused tracts of geoids
'''
def unused_tract_mapping(used_tracts, districts_dict, all_tracts, max_pop, min_pop, avg_pop, num_districts):
num_districts = len(districts_dict)
unused_tracts = set()
newly_added = {}
for single_tract in all_tracts:
for single_tract in state_tracts:
if single_tract not in used_tracts:
unused_tracts.add(single_tract)
return unused_tracts
def plus_total_population_D_R(district_plan, district_num, tract_total ,tract_dem, tract_rep):
'''
Reason
Inputs:
district_plan: a dictionary of dictionaries containing a tract plans in the state
num_districts: an integer indicating the total number of districts to be constructed
tract_total: a float
tract_dem: a float
tract_rep: a float
Returns: nothing
'''
district_plan[district_num]["total_population"] += tract_total
district_plan[district_num]["D"] += tract_dem
district_plan[district_num]["R"] += tract_rep
def minus_total_population_D_R(district_plan, district_num, tract_total, tract_dem, tract_rep):
'''
Reason
Inputs:
district_plan: a dictionary of dictionaries containing a tract plans in the state
district_num: a interger
tract_total: a float
tract_dem: a float
tract_rep: a float
Returns: nothing
'''
district_plan[district_num]["total_population"] -= tract_total
district_plan[district_num]["D"] -= tract_dem
district_plan[district_num]["R"] -= tract_rep
def population_check(districts_dict, max_pop, min_pop, avg_pop):
'''
Reason
Inputs:
districts_dict: a dictionary of dictionaries containing a tract plans in the state
max_pop: a float, maximum population for a district
min_pop: a interger, minimum population for a district
avg_pop: a interger, average population for a district
Returns: a interger
'''
largest_diffence = 0
largest_num = 0
for num in districts_dict:
population_district = districts_dict[num]["total_population"]
if population_district <= min_pop or population_district >= max_pop:
population_difference = population_district - avg_pop
if abs(population_difference) >= abs(largest_diffence):
largest_diffence = population_difference
largest_num = num
return largest_num
def put_unused_in_district_plan(used_tracts, unused_tracts, district_plan, all_tracts):
'''
Reason
Inputs:
used_tracts: a dictionary containing used geoid ids, a string and its district placeement, a interger
unused_tracts: a sets of strings, containing a geoid ids not using
district_plan: a dictionary of dictionaries containing a tract plans in the state
all_tracts: a dictionary of dictionaries containing the data on all tracts in the state
Returns: nothing
'''
# Print Statement Delete Later - Start
printer = ["old"]
for num in district_plan:
printer.append(district_plan[num]["total_population"])
printer.append(calculate_efficiency_gap_from_dict(district_plan))
print(printer)
# Print Statement Delete Later - End
unused_tracts_run = set(unused_tracts)
for single_unused in unused_tracts_run:
adjacent = all_tracts[single_unused]["connections"]
tract_total = all_tracts[single_unused]["total_population"]
tract_dem = all_tracts[single_unused]["D"]
tract_rep = all_tracts[single_unused]["R"]
best_district = 0
best_gap = 1000000000
for adj in adjacent:
if adj in used_tracts:
district_adj = used_tracts[adj]
if (district_adj - best_district):
plus_total_population_D_R(district_plan, district_adj, tract_total ,tract_dem, tract_rep)
new_gap = calculate_efficiency_gap_from_dict(district_plan)
minus_total_population_D_R(district_plan, district_adj, tract_total ,tract_dem, tract_rep)
if abs(new_gap) < abs(best_gap):
best_district = district_adj
best_tract = single_unused
best_gap = new_gap
best_total = tract_total
best_dem = tract_dem
best_rep = tract_rep
if best_district:
unused_tracts.remove(best_tract)
used_tracts[best_tract] = best_district
if best_district not in used_tracts:
new_population = all_tracts[best_tract]["total_population"]
district_plan[best_district]["tracts"].append(single_unused)
plus_total_population_D_R(district_plan, best_district, best_total ,best_dem, best_rep)
def fix_district_population_too_large(used_tracts, districts_dict, all_tracts, max_pop, min_pop, avg_pop, count, check_pop):
'''
Reason
Inputs:
used_tracts: a dictionary containing a geoid id, a string and it's district placeement, a interger
districts_dict: a dictionary of dictionaries containing a tract plans in the state
all_tracts: a dictionary of dictionaries containing the data on all tracts in the state
max_pop: a interger, maximum population for a district
min_pop: a interger, minimum population for a district
avg_pop: a interger, average population for a district
count: a interger, number of while loop runs
check_pop: a interger, currented district number being checked
Returns: nothing
'''
count += 1
tracts_districts = set(districts_dict[check_pop]["tracts"])
for single_tract in tracts_districts:
adjacent = all_tracts[single_tract]["connections"]
tract_total = all_tracts[single_tract]["total_population"]
tract_dem = all_tracts[single_tract]["D"]
tract_rep = all_tracts[single_tract]["R"]
best_district = None
best_gap = 2
minus_total_population_D_R(districts_dict, check_pop, tract_total ,tract_dem, tract_rep)
for adj in adjacent:
district_adj = used_tracts[adj]
if adj not in tracts_districts:
plus_total_population_D_R(districts_dict, district_adj, tract_total ,tract_dem, tract_rep)
new_gap = calculate_efficiency_gap_from_dict(districts_dict)
minus_total_population_D_R(districts_dict, district_adj, tract_total ,tract_dem, tract_rep)
if abs(new_gap) < abs(best_gap):
best_total = tract_total
best_dem = tract_dem
best_rep = tract_rep
best_district = district_adj
best_tract = single_tract
best_gap = new_gap
if best_district:
districts_dict[check_pop]["tracts"].remove(single_tract)
districts_dict[best_district]["tracts"].add(single_tract)
used_tracts[single_tract] = best_district
plus_total_population_D_R(districts_dict, best_district, best_total ,best_dem, best_rep)
elif not best_district:
plus_total_population_D_R(districts_dict, check_pop, tract_total ,tract_dem, tract_rep)
if count > 40:
return
def fix_district_population_too_small(used_tracts, districts_plan, all_tracts, max_pop, min_pop, avg_pop, count, check_pop):
'''
Reason
Inputs:
used_tracts: a dictionary containing a geoid id, a string and it's district placeement, a interger
districts_dict: a dictionary of dictionaries containing a tract plans in the state
all_tracts: a dictionary of dictionaries containing the data on all tracts in the state
max_pop: a interger, maximum population for a district
min_pop: a interger, minimum population for a district
avg_pop: a interger, average population for a district
count: a interger, number of while loop runs
check_pop: a interger, currented district number being checked
Returns: nothing
'''
count += 1
tracts_districts = set(districts_plan[check_pop]["tracts"])
for single_tract in tracts_districts:
adjacent = all_tracts[single_tract]["connections"]
best_district = None
best_gap = 2
for adj in adjacent:
if adj not in tracts_districts:
district_adj = used_tracts[adj]
total_pop_district = districts_plan[district_adj]["total_population"]
if total_pop_district >= 0:
tract_total = all_tracts[adj]["total_population"]
tract_dem = all_tracts[adj]["D"]
tract_rep = all_tracts[adj]["R"]
plus_total_population_D_R(districts_plan, check_pop, tract_total ,tract_dem, tract_rep)
minus_total_population_D_R(districts_plan, district_adj, tract_total ,tract_dem, tract_rep)
new_gap = calculate_efficiency_gap_from_dict(districts_plan)
minus_total_population_D_R(districts_plan, check_pop, tract_total ,tract_dem, tract_rep)
plus_total_population_D_R(districts_plan, district_adj, tract_total ,tract_dem, tract_rep)
if abs(new_gap) < abs(best_gap):
best_pop = tract_total
best_dem = tract_dem
best_rep = tract_rep
best_district = district_adj
best_tract = adj
best_gap = new_gap
if best_district:
districts_plan[best_district]["tracts"].remove(best_tract)
districts_plan[check_pop]["tracts"].add(best_tract)
used_tracts[best_tract] = check_pop
# Check Plus - Best
plus_total_population_D_R(districts_plan, check_pop, best_pop ,best_dem, best_rep)
# ADJ Minus - Best
minus_total_population_D_R(districts_plan, district_adj, best_pop ,best_dem, best_rep)
if count > 40:
return
def unused_tract_mapping(used_tracts, districts_dict, all_tracts, max_pop, min_pop, avg_pop, num_districts):
'''
Reason
Inputs:
used_tracts: a dictionary containing a geoid id, a string and it's district placeement, a interger
districts_dict: a dictionary of dictionaries containing a tract plans in the state
all_tracts: a dictionary of dictionaries containing the data on all tracts in the state
max_pop: a interger, maximum population for a district
min_pop: a interger, minimum population for a district
avg_pop: a interger, average population for a district
num_districts: an integer indicating the total number of districts to be constructed
Returns: a dictionary of dictionaries containing a tract plans in the state
'''
unused_tracts = get_unused_set(all_tracts, used_tracts)
while unused_tracts:
print(len(used_tracts))
printer = ["old"]
put_unused_in_district_plan(used_tracts, unused_tracts,
districts_dict, all_tracts)
districts_dict = district_plan_add_sets(districts_dict)
acceptable_max = int(max_pop / num_districts)
acceptable_min = int(min_pop / num_districts)
check_pop = population_check(districts_dict, acceptable_max, acceptable_min, avg_pop)
while check_pop:
count = 0
while districts_dict[check_pop]["total_population"] >= acceptable_max:
fix_district_population_too_large(used_tracts, districts_dict,
all_tracts, max_pop, min_pop, avg_pop, count, check_pop)
while districts_dict[check_pop]["total_population"] <= acceptable_min:
fix_district_population_too_small(used_tracts, districts_dict,
all_tracts, max_pop, min_pop, avg_pop, count, check_pop)
check_pop = population_check(districts_dict, acceptable_max, acceptable_min, avg_pop)
# Print Statement Delete Later - Start
printer = ["new"]
for num in districts_dict:
printer.append(districts_dict[num]["total_population"])
printer.append(calculate_efficiency_gap_from_dict(districts_dict))
print(printer)
# Print Statement Delete Later - End
unused_tracts_run = set(unused_tracts)
for single_unused in unused_tracts_run:
adjacent = all_tracts[single_unused]["connections"]
best_district = 0
district_adj = 1
best_gap = 1000000000
for adj in adjacent:
if adj in used_tracts:
district_adj = used_tracts[adj]
if (district_adj - best_district):
new_gap = calculate_efficiency_gap_from_dict(districts_dict)
if abs(new_gap) < abs(best_gap):
best_district = district_adj
best_tract = single_unused
best_gap = new_gap
if best_district:
unused_tracts.remove(single_unused)
used_tracts[best_tract] = best_district
if best_district not in used_tracts:
new_population = all_tracts[best_tract]["total_population"]
districts_dict[best_district]["tracts"].append(single_unused)
districts_dict[best_district]["total_population"] += new_population
districts_dict = district_plan_add_sets(districts_dict)
difference = 0
true_max = int(max_pop / num_districts)
true_min = int(min_pop / num_districts)
acceptable_max = int(max_pop / num_districts - difference)
acceptable_min = int(min_pop / num_districts + difference)
return districts_dict
check_pop = population_check(districts_dict, true_max, true_min, avg_pop)
while check_pop:
count = 0
while districts_dict[check_pop]["total_population"] >= acceptable_max:
count += 1
direction = 1
def find_largest_wasted(district_plan):
'''
Reason
tracts_districts = set(districts_dict[check_pop]["tracts"])
# print(districts_dict[check_pop]["tracts"])
# print(100)
Inputs:
district_plan: a dictionary of dictionaries containing a tract plans in the state
# print(101)
for single_tract in tracts_districts:
adjacent = all_tracts[single_tract]["connections"]
total_pop = all_tracts[single_tract]["total_population"]
total_dem = all_tracts[single_tract]["D"]
total_rep = all_tracts[single_tract]["R"]
Returns:
# print(total_pop)
best_district = 0
best_gap = 9999999
districts_dict[check_pop]["total_population"] -= total_pop
districts_dict[check_pop]["D"] -= total_dem
districts_dict[check_pop]["R"] -= total_rep
for adj in adjacent:
total_pop_district = districts_dict[district_adj]["total_population"]
if total_pop_district <= max_pop:
if adj not in tracts_districts:
district_adj = used_tracts[adj]
districts_dict[district_adj]["total_population"] += total_pop
districts_dict[district_adj]["D"] += total_dem
districts_dict[district_adj]["R"] += total_rep
new_gap = calculate_efficiency_gap_from_dict(districts_dict)
districts_dict[district_adj]["total_population"] -= total_pop
districts_dict[district_adj]["D"] -= total_dem
districts_dict[district_adj]["R"] -= total_rep
if abs(new_gap) < abs(best_gap):
best_district = district_adj
best_tract = single_tract
best_gap = new_gap
if best_district:
districts_dict[check_pop]["tracts"].remove(single_tract)
districts_dict[best_district]["tracts"].add(single_tract)
used_tracts[single_tract] = best_district
districts_dict[best_district]["total_population"] += total_pop
districts_dict[best_district]["D"] += total_dem
districts_dict[best_district]["R"] += total_rep
elif not best_district:
districts_dict[check_pop]["total_population"] += total_pop
districts_dict[check_pop]["D"] += total_dem
districts_dict[check_pop]["R"] += total_rep
'''
highest_wasted_num = 0
highest_wasted_district = None
for district in district_plan.keys():
rep_votes = district_plan[district]["R"]
dem_votes = district_plan[district]["D"]
#Check which party wins the district, then calculate both parties' wasted votes
if rep_votes > dem_votes:
wasted_rvotes = (rep_votes - (rep_votes + dem_votes) / 2)
wasted_dvotes = dem_votes
if wasted_dvotes > highest_wasted_num:
highest_wasted_num = 0
highest_wasted_district = district
if count > 40:
break
else:
wasted_rvotes = rep_votes
wasted_dvotes = (dem_votes - (rep_votes + dem_votes) / 2)
while districts_dict[check_pop]["total_population"] <= acceptable_min:
count += 1
if wasted_rvotes > wasted_dvotes:
if wasted_rvotes > highest_wasted_num:
highest_wasted_num = wasted_rvotes
highest_wasted_district = district
else:
if wasted_rvotes > highest_wasted_num:
highest_wasted_num = wasted_rvotes
highest_wasted_district = district
return highest_wasted_district
def make_gap_lower(districts_dict, all_tracts, num_districts, used_tracts, goal, min_pop, max_pop):
'''
Use the efficiency gap to construct an optimal district plan for a state that incorporates
a percentage of the population greater than or equal to the percent_of_people argument
If it is impossible to construct a district plan that meets the population threshold, return 0.
Inputs:
districts_dict
all_tracts
num_districts
used_tracts
goal
min_pop
max_pop
Returns:
a dictionary of dictionaries containing a tract plans in the state
a interger,
'''
count = 0
gap = calculate_efficiency_gap_from_dict(districts_dict)
goal_percent = goal / 100
print(goal_percent, gap)
while abs(gap) > goal_percent and (count - 4500):
count += 1
new = False
check_pop = random.choice(range(1,num_districts+1))
best_gap = calculate_efficiency_gap_from_dict(districts_dict)
while not new:
new_count = 0
new_count += 1
new = True
tracts_districts = set(districts_dict[check_pop]["tracts"])
# print(districts_dict[check_pop]["tracts"])
# print(100)
best_district = None
# print(101)
for single_tract in tracts_districts:
adjacent = all_tracts[single_tract]["connections"]
# print(total_pop)
tract_total = all_tracts[single_tract]["total_population"]
tract_dem = all_tracts[single_tract]["D"]
tract_rep = all_tracts[single_tract]["R"]
best_district = 0
best_gap = 9999999
for adj in adjacent:
if adj not in tracts_districts:
minus_total_population_D_R(districts_dict, check_pop, tract_total ,tract_dem, tract_rep)
if districts_dict[check_pop]["total_population"] > min_pop:
for adj in adjacent:
district_adj = used_tracts[adj]
total_pop = all_tracts[adj]["total_population"]
total_pop_district = districts_dict[district_adj]["total_population"]
if total_pop_district >= 0:
total_pop = all_tracts[adj]["total_population"]
total_dem = all_tracts[adj]["D"]
total_rep = all_tracts[adj]["R"]
# CHECK Plus
districts_dict[check_pop]["total_population"] += total_pop
districts_dict[check_pop]["D"] += total_dem
districts_dict[check_pop]["R"] += total_rep
# ADJ Minus
districts_dict[district_adj]["total_population"] -= total_pop
districts_dict[district_adj]["D"] -= total_dem
districts_dict[district_adj]["R"] -= total_rep
# Calcuate
new_gap = calculate_efficiency_gap_from_dict(districts_dict)
# CHECK Minus
districts_dict[check_pop]["total_population"] -= total_pop
districts_dict[check_pop]["D"] -= total_dem
districts_dict[check_pop]["R"] -= total_rep
# ADJ Plus
districts_dict[district_adj]["total_population"] += total_pop
districts_dict[district_adj]["D"] += total_dem
districts_dict[district_adj]["R"] += total_rep
if abs(new_gap) < abs(best_gap):
best_pop = total_pop
best_dem = total_dem
best_rep = total_rep
best_district = district_adj
best_tract = adj
best_gap = new_gap
if adj not in tracts_districts:
plus_total_population_D_R(districts_dict, district_adj, tract_total ,tract_dem, tract_rep)
if districts_dict[district_adj]["total_population"] < max_pop:
new_gap = calculate_efficiency_gap_from_dict(districts_dict)
# print("hit", new_gap != best_gap)
if abs(new_gap) <= abs(best_gap):
new = False
best_total = tract_total
best_dem = tract_dem
best_rep = tract_rep
best_district = district_adj
best_tract = single_tract
best_gap = new_gap
minus_total_population_D_R(districts_dict, district_adj, tract_total ,tract_dem, tract_rep)
plus_total_population_D_R(districts_dict, check_pop, tract_total ,tract_dem, tract_rep)
if best_district:
districts_dict[best_district]["tracts"].remove(best_tract)
districts_dict[check_pop]["tracts"].add(best_tract)
used_tracts[best_tract] = check_pop
# Check Plus - Best
districts_dict[check_pop]["total_population"] += best_pop
districts_dict[check_pop]["D"] += best_dem
districts_dict[check_pop]["R"] += best_rep
# ADJ Minus - Best
districts_dict[district_adj]["total_population"] -= best_pop
districts_dict[district_adj]["D"] -= best_dem
districts_dict[district_adj]["R"] -= best_rep
if count > 40:
break
check_pop = population_check(districts_dict, true_max, true_min, avg_pop)
printer = ["new"]
districts_dict[check_pop]["tracts"].remove(best_tract)
districts_dict[best_district]["tracts"].add(best_tract)
used_tracts[single_tract] = best_district
plus_total_population_D_R(districts_dict, best_district, best_total ,best_dem, best_rep)
minus_total_population_D_R(districts_dict, check_pop, best_total ,best_dem, best_rep)
for num in districts_dict:
printer.append(districts_dict[num]["total_population"])
printer.append(calculate_efficiency_gap_from_dict(districts_dict))
print(printer)
#print(type(new_district_plan))
# >>>>>>> 7bf9bdd222d407502b3fa2b517e39d70d090d88e
gap = calculate_efficiency_gap_from_dict(districts_dict)
printer = ["lower", check_pop, count]
for num in districts_dict:
printer.append(districts_dict[num]["total_population"])
printer.append(calculate_efficiency_gap_from_dict(districts_dict))
print(printer)
return districts_dict, count
return districts_dict
def population_check(districts_dict, max_pop, min_pop, avg_pop):
largest_diffence = 0
largest_num = 0
for num in districts_dict:
population_district = districts_dict[num]["total_population"]
if population_district <= min_pop or population_district >= max_pop:
population_difference = population_district - avg_pop
if abs(population_difference) >= abs(largest_diffence):
largest_diffence = population_difference
largest_num = num
return largest_num
def completed_result(state, initial_percent_of_people, speical_name=''):
def completed_result(state, initial_percent_of_people=60, goal=5, special_name=''):
'''
Gets the final districts plan for a entire state's population
and outputs district plan to a file.
Inputs:
state: a string, state name captalized
initial_percent_of_people: a interger, the percent of people used for drawing
special_name: a string, specialized names for district plan output file
Returns: a dictionary of dictionaries containing a tract plans in the state
'''
state_tract, num_districts = set_tracts(state=state)
if not num_districts:
return
total_population = 0
for tract in state_tract.values():
total_population += tract["total_population"]
avg_pop = total_population / 4
avg_pop = total_population / num_districts
max_pop = total_population * 1.1
min_pop = total_population * 0.9
......@@ -753,25 +985,39 @@ def completed_result(state, initial_percent_of_people, speical_name=''):
unused_tract_mapping(used_tracts, districts_dict, state_tract, max_pop, min_pop, avg_pop, num_districts)
create_json_file(districts_dict, "district_plans/"+ state + speical_name)
max_pop_district = int(max_pop / num_districts)
min_pop_district = int(min_pop / num_districts)
used_tracts = {}
for num in districts_dict:
tract_list = districts_dict[num]["tracts"]
for single_tract in tract_list:
used_tracts[single_tract] = num
make_gap_lower(districts_dict, state_tract,num_districts, used_tracts, goal, min_pop_district, max_pop_district)
create_json_file(districts_dict, "district_plans/"+ state + special_name)
return districts_dict
def all_states_result(initial_percent_of_people, speical_name=''):
def all_states_result(initial_percent_of_people, special_name=''):
'''
Gets the final districts plan for a every state and outputs all district plans.
Inputs:
state: state name captalized (a string)
initial_percent_of_people: the percent of people used for drawing (a interger)
special_name: specialized names for district plan output file (a string)
Returns: nothing
'''
master_tracts = set_tracts()
for state in master_tracts:
print(state)
completed_result(state, initial_percent_of_people, speical_name='')
# return (num, "large")
# if len(set_num):
# random_num = random.choice(set_num)
# print(random_num)
# return random_num
# if not len(set_num):
# return None
completed_result(state, initial_percent_of_people, special_name=special_name)
def district_plan_add_sets(districts_plan):
for num in districts_plan:
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -3,8 +3,6 @@ import json
import ast
from util import create_json_file, recover_json
shapefile_path = "Census_tract/Tract_2010Census_DP1.shp"
def get_shapeRecs(shapefile_path):
......@@ -46,7 +44,7 @@ def get_connects_tracts(sf_connect):
dict_tracts = {}
for sh_num1, sh_num2 in sf_connect:
if sh_num1 not in dict_tracts:
dict_traics[sh_num1] = [sh_num2]
dict_tracts[sh_num1] = [sh_num2]
count += 1
if sh_num1 in dict_tracts:
if sh_num2 not in dict_tracts[sh_num1]:
......@@ -149,6 +147,8 @@ def gender_RD(record):
2012 exit poll data, found here: http://www.cnn.com/election/2012/results/race/president/
'''
total_population = record[6]
weight_R = 0
weight_D = 0
......@@ -160,18 +160,22 @@ def gender_RD(record):
weight_D += pop_female * -0.12
total_population_above_16 = pop_female + pop_male
if not total_population_above_16:
return 0.0
population_change = 1 - (total_population_above_16/total_population) + 1
weight_D = weight_D * population_change
weight_R = weight_R * population_change
add_weights = weight_R + weight_D
if not add_weights:
return 0.0
percent_RD =((add_weights)/(abs(weight_D)+weight_R))
return percent_RD
percent_RD =( (add_weights)/(abs(weight_D)+weight_R))
return percent_RD
def get_populations_RD(shapeRecs, connect_tracts, state_set):
......@@ -219,7 +223,6 @@ def get_populations_RD(shapeRecs, connect_tracts, state_set):
def create_state_tracts(shapeRecs):
'''
Recover the json files created in location_api.py that have sorted tracts by state
......@@ -261,4 +264,5 @@ def state_tracts_hard_coded(Master_tract_dicts):
Master_tract_dicts[state][new_connection]["connections"].append(tract)
single_state_dict = Master_tract_dicts[state]
create_json_file(single_state_dict, "state_tracts_full_json_files/" + state + "tract_dict")
return Master_tract_dicts
\ No newline at end of file
return Master_tract_dicts
......@@ -68,8 +68,7 @@ def hard_code(output=False):
"11001009700": "District of Columbia",
"15009990200": "Hawaii",
"23005990000": "Maine",
"26001990000":"Michigan",
"26001990000": "Michigan",
"26009990000": "Michigan",
"26157990000": "Michigan",
"28047990000": "Mississippi",
......
......@@ -35,3 +35,4 @@ def color_csv(path, file_name):
count += 1
return colors_dict
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment