Exemplo n.º 1
0
def updaters_MC(settings):
    my_updaters = {
        "cut_edges": cut_edges,
        "population": updaters.Tally("TOTPOP", alias = "population"),
        "avg_pop_dist": avg_pop_dist,
        "pop_dist_pct" : pop_dist_pct,
        "area_land": updaters.Tally("ALAND10", alias = "area_land"),
        "area_water": updaters.Tally("AWATER10", alias = "area_water"),
        "Perimeter": updaters.Tally("perimeter", alias = "Perimeter"),
        "Area": updaters.Tally("area", alias = "Area")}
    num_elections = settings['num_elections']
    election_names = settings['election_names']
    election_columns = settings['election_columns']
    num_steps = settings['num_steps']
    interval = settings['interval']
    pop_tol = settings['pop_tol']
    
    elections = [
        Election(
            election_names[i],
            {"Democratic": election_columns[i][0], "Republican": election_columns[i][1]},
        ) for i in range(num_elections)]

    election_updaters = {election.name: election for election in elections}

    my_updaters.update(election_updaters)
    return(my_updaters)
Exemplo n.º 2
0
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
Exemplo n.º 3
0
def test_pa_freeze():
    from gerrychain import (
        GeographicPartition,
        Graph,
        MarkovChain,
        proposals,
        updaters,
        constraints,
        accept,
    )
    import hashlib
    from gerrychain.proposals import recom
    from functools import partial

    graph = Graph.from_json("docs/user/PA_VTDs.json")

    my_updaters = {"population": updaters.Tally("TOTPOP", alias="population")}
    initial_partition = GeographicPartition(graph,
                                            assignment="CD_2011",
                                            updaters=my_updaters)

    ideal_population = sum(
        initial_partition["population"].values()) / len(initial_partition)

    # We use functools.partial to bind the extra parameters (pop_col, pop_target, epsilon, node_repeats)
    # of the recom proposal.
    proposal = partial(recom,
                       pop_col="TOTPOP",
                       pop_target=ideal_population,
                       epsilon=0.02,
                       node_repeats=2)

    pop_constraint = constraints.within_percent_of_ideal_population(
        initial_partition, 0.02)

    chain = MarkovChain(
        proposal=proposal,
        constraints=[pop_constraint],
        accept=accept.always_accept,
        initial_state=initial_partition,
        total_steps=100,
    )

    result = ""
    for count, partition in enumerate(chain):
        result += str(list(sorted(partition.population.values())))
        result += str(len(partition.cut_edges))
        result += str(count) + "\n"

    assert hashlib.sha256(result.encode()).hexdigest(
    ) == "3bef9ac8c0bfa025fb75e32aea3847757a8fba56b2b2be6f9b3b952088ae3b3c"
Exemplo n.º 4
0
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)
Exemplo n.º 5
0
def run_chain(adj_graph, elections, total_steps=100):
    my_updaters = {
        "population": updaters.Tally("population"),
        "cut_edges": cut_edges,
        "elections": lambda x: [elec.alias for elec in elections],
        "expected_seat_share": expected_seat_share_updater
    }
    election_updaters = {election.name: election for election in elections}
    my_updaters.update(election_updaters)

    initial_partition = GeographicPartition(adj_graph,
                                            assignment="initial_plan",
                                            updaters=my_updaters)
    ideal_population = sum(
        initial_partition["population"].values()) / len(initial_partition)
    proposal = partial(recom,
                       pop_col="population",
                       pop_target=ideal_population,
                       epsilon=0.01,
                       node_repeats=2)
    pop_constraint = constraints.within_percent_of_ideal_population(
        initial_partition, 0.01)
    chain = MarkovChain(proposal=proposal,
                        constraints=[
                            pop_constraint,
                        ],
                        accept=accept.always_accept,
                        initial_state=initial_partition,
                        total_steps=total_steps)

    return pd.DataFrame({
        ix: {
            "cut_edges": len(partition["cut_edges"]),
            "expected_R_seats": partition["expected_seat_share"]
        }
        for ix, partition in enumerate(chain)
    }).T
Exemplo n.º 6
0
def main(graph_json, shp, n_steps, output_dir, prefix, seed, pop_col, pop_tol,
         plan_col, reproject, election):
    os.makedirs(output_dir, exist_ok=True)
    has_geometry = False
    if not shp and not graph_json:
        print('Specify a shapefile or a NetworkX-format graph '
              'JSON file.',
              file=sys.stderr)
        sys.exit(1)
    elif shp and not graph_json:
        gdf = gpd.read_file(shp)
        if reproject:
            gdf = reprojected(gdf)
        graph = Graph.from_geodataframe(gdf)
        has_geometry = True
    elif graph_json and not shp:
        graph = Graph.from_json(graph_json)
    else:
        graph = Graph.from_json(graph_json)
        gdf = gpd.read_file(shp)
        if reproject:
            gdf = reprojected(gdf)
        print('Appending geometries from shapefile to graph...')
        graph.geometry = gdf.geometry  # TODO: is this always valid?
        has_geometry = True

    my_updaters = {'population': updaters.Tally(pop_col, alias='population')}
    if election:
        election_up = Election('election', {
            'Democratic': election[0],
            'Republican': election[1]
        })
        my_updaters['election'] = election_up
    initial_state = GeographicPartition(graph,
                                        assignment=plan_col,
                                        updaters=my_updaters)

    normal_chain = RecomChain(graph=graph,
                              total_steps=n_steps,
                              initial_state=initial_state,
                              pop_col=pop_col,
                              pop_tol=pop_tol,
                              reversible=False,
                              seed=seed)
    reversible_chain = RecomChain(graph=graph,
                                  total_steps=n_steps,
                                  initial_state=initial_state,
                                  pop_col=pop_col,
                                  pop_tol=pop_tol,
                                  reversible=True,
                                  seed=seed)

    normal_plans = [plan for plan in tqdm(normal_chain)]
    reversible_plans = [plan for plan in tqdm(reversible_chain)]
    cut_edges_fig(output_dir, prefix, normal_plans, reversible_plans)
    longest_boundary_fig(output_dir, prefix, normal_plans, reversible_plans)
    if has_geometry:
        demo_plans(output_dir, '_'.join([prefix, 'recom']), normal_plans,
                   n_steps, n_steps // 25)
        demo_plans(output_dir, '_'.join([prefix, 'reversible_recom']),
                   reversible_plans, n_steps, n_steps // 25)
    if election:
        election_hists(output_dir, 'dem_vote_share', 'election', 'Democratic',
                       normal_plans, reversible_plans)
    acceptance_stats(output_dir, '_'.join([prefix, 'recom']), normal_plans)
    acceptance_stats(output_dir, '_'.join([prefix, 'reversible_recom']),
                     reversible_plans)
def subset_list(percentage_list, lower_threshold, upper_threshold):
    percentage_intermediate = percentage_list[
        percentage_list >= lower_threshold]
    return len(
        percentage_intermediate[percentage_intermediate < upper_threshold])


# ---- Load in graph ------\
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],
Exemplo n.º 8
0
election_names = [
    "PRES12",
    "PRES16",
    "SENW101216",
]
election_columns = [
    ["PRES12D", "PRES12R"],
    ["T16PRESD", "T16PRESR"],
    ["W101216D", "W101216R"],
]

graph = Graph.from_json(graph_path)

updaters = {
    "population": updaters.Tally("TOT_POP", alias="population"),
    "cut_edges": cut_edges,
}

elections = [
    Election(
        election_names[i],
        {
            "Democratic": election_columns[i][0],
            "Republican": election_columns[i][1]
        },
    ) for i in range(num_elections)
]

election_updaters = {election.name: election for election in elections}
Exemplo n.º 9
0
whole_start = time.time()

# Initialization
df = gpd.read_file("./AK_precincts_ns/AK_precincts_ns/AK_precincts_ns.shp")
df["nAMIN"] = df["TOTPOP"] - df["AMIN"]
elections = [
    Election("GOV18x", {"Democratic": "GOV18D_x", "Republican": "GOV18R_x"}),
    Election("USH18x", {"Democratic": "USH18D_x", "Republican": "USH18R_x"}),
    Election("GOV18ns", {"Democratic": "GOV18D_NS", "Republican": "GOV18R_NS"}),
    Election("USH18ns", {"Democratic": "USH18D_NS", "Republican": "USH18R_NS"}),
    Election("Native_percent", {"Native": "AMIN", "nonNative": "nAMIN"}),
]

my_updaters = {
    "population": updaters.Tally("POPULATION", alias="population"),
    "cut_edges": cut_edges,
}

election_updaters = {election.name: election for election in elections}

my_updaters.update(election_updaters)


# Construct Dual Graphs


# Tightest Alaska
print("Building Tight Graph")

G_tight = Graph.from_file("./AK_precincts_ns/AK_precincts_ns/AK_precincts_ns.shp")
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
    partition.plot(geometries=va_precincts.geometry, cmap='tab20')
    plt.savefig(newdir + "plot" + str(count) + ".png")
    plt.close()

#Use ReCom to build gerrychain and plot.
elections = [
    Election("PRES16", {
        "Dem": "G16DPRS",
        "Rep": "G16RPRS"
    }),
    Election("SEN12", {
        "Dem": "G18DSEN",
        "Rep": "G18RSEN"
    })
]
my_updaters = {"population": updaters.Tally("TOTPOP", alias="population")}
election_updaters = {election.name: election for election in elections}
my_updaters.update(election_updaters)
initial_partition = GeographicPartition(graph,
                                        assignment="CD_16",
                                        updaters=my_updaters)
# The ReCom proposal needs to know the ideal population for the districts so that
# we can improve speed by bailing early on unbalanced partitions.

ideal_population = sum(
    initial_partition["population"].values()) / len(initial_partition)

# We use functools.partial to bind the extra parameters (pop_col, pop_target, epsilon, node_repeats)
# of the recom proposal.
proposal = partial(recom,
                   pop_col="TOTPOP",
Exemplo n.º 12
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"]})


def cut_length(partition):
    return len(partition["cut_edges"])


updater = {
    "population": updaters.Tally("TOT_POP"),
    "cut_edges": cut_edges,
    "step_num": step_num,
    'b_nodes': b_nodes_bi
}

initial_partition = Partition(g, "GOV", updater)

compactness_bound = constraints.UpperBound(cut_length,
                                           cut_length(initial_partition))

cols = [
    "GOV", "TS", "REMEDIAL_P", "538CPCT__1", "538DEM_PL", "538GOP_PL",
    "8THGRADE_1"
]
Exemplo n.º 13
0
    """
    return {
        part: compute_reock(partition, part, partition["area"][part])
        for part in partition.parts
    }


# ---- Load in graph ------
#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"),
    "VAP": updaters.Tally(VAP_col, alias="VAP"),
    "num_vra_districts": num_vra_districts,
    "num_opp_districts": num_opp_districts,
    "county_splits": county_splits("county_splits", county_assignment_col)
}

num_elections = len(election_names)

elections = [
    Election(
        election_names[i],
        {
Exemplo n.º 14
0
    fid_to_node = {}
    f = open(filename, 'r')
    f.readline()
    for line in f:
        lineitems = line.rstrip("\n").split("\t")
        fid, geoid = int(lineitems[0]), lineitems[1]
        geoid_to_fid[geoid] = fid
    for n in graph.nodes:
        fid_to_node[geoid_to_fid[graph.nodes[n][geoidcol]]] = n
    return fid_to_node


#set up geography and elections
pop_col = "TOTPOP"
my_updaters = {
    "population": updaters.Tally(pop_col, alias="population"),
    "cut_edges": cut_edges,
}

import os

folder = "districtMaps"
fid_to_geoid_file = "./preprocessedData/arcgis_FIDtovtdkeymap.txt"
geoidcol = "VTD"
files = []
pop_col = "TOTPOP"
for filename in os.listdir(folder):
    #print(filename)
    files.append("./" + folder + "/" + filename)

total_population = sum([graph.nodes[n][pop_col] for n in graph.nodes()])

print("Shapefiles loaded and ready to run ReCom...")

'''
Run the chain
'''
for k in [num_districts]:
    HISPs = []
    POPs = []
    BPOPs = []
    pop_target = total_population/k
    myproposal = partial(recom, pop_col=pop_col, pop_target=pop_target, epsilon=pop_tol/k, node_repeats=2)
    #updaters
    myupdaters = {
        "population": updaters.Tally(pop_col, alias="population"),
        "HISP": updaters.Tally("HISP", alias="HISP"),
        "BPOP": updaters.Tally("NH_BLACK", alias="BPOP")
    }

    #initial partition
    initial_ass = littlehelpers.factor_seed(graph, k, pop_tol, pop_col)
    initial_partition = Partition(graph, initial_ass, myupdaters)

    #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),
Exemplo n.º 16
0
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)
Exemplo n.º 17
0
    centroids = {k: (CXs[k], CYs[k]) for k in list(partition.parts.keys())}
    return centroids


def num_cut_edges(partition):
    return len(partition["cut_edges"])


def num_county_splits(partition, df=state_gdf):
    df["current"] = df.index.map(partition.assignment.to_dict())
    return sum(df.groupby(county_split_id)['current'].nunique() > 1)


#####construct updaters for Chain###############################################
my_updaters = {
    "population": updaters.Tally(tot_pop, alias="population"),
    "CVAP": updaters.Tally(CVAP, alias="CVAP"),
    "WCVAP": updaters.Tally(WCVAP, alias="WCVAP"),
    "HCVAP": updaters.Tally(HCVAP, alias="HCVAP"),
    "BCVAP": updaters.Tally(BCVAP, alias="BCVAP"),
    "Sum_CX": updaters.Tally(C_X, alias="Sum_CX"),
    "Sum_CY": updaters.Tally(C_Y, alias="Sum_CY"),
    "cut_edges": cut_edges,
    "num_cut_edges": num_cut_edges,
    "num_county_splits": num_county_splits,
    "demo_percents": demo_percents,
    "final_elec_model": final_elec_model,
    "centroids": centroids
}

#add elections updaters
Exemplo n.º 18
0
    "BVAP",
    "LTGOV",
    "GOV",
    "AG"]

election_columns = [
    ["VAPBLACK", "nBVAP"],
    ["D_LTGOV", "R_LTGOV"],
    ["D_GOV", "R_GOV"],
    ["D_ATTGEN", "R_ATTGEN"],
    ["PRES12D", "PRES12R"],
    ]


updater = {
    "population": updaters.Tally("TAPERSONS", alias="population"),
    "cut_edges": cut_edges,
    'b_nodes':b_nodes,
}

elections = [
    Election(
        election_names[i],
        {"First": election_columns[i][0], "Second": election_columns[i][1]},
    )
    for i in range(num_elections)
]

election_updaters = {election.name: election for election in elections}

updater.update(election_updaters)
Exemplo n.º 19
0
def MC_sample(jgraph, settings, save_part = True):
    """
    :param jgraph: gerrychain Graph object
    :param settings: settings dictionary (possibly loaded from a yaml file) with election info, MC parameters, and constraints params (see settings.yaml file for an example of the structure needed)
    :param save_part: True is you want to save the partition as json 
    :returns: a list of partitions sapmpled every interval step
    """
    my_updaters = {
        "cut_edges": cut_edges,
        "population": updaters.Tally("TOTPOP", alias = "population"),
        "avg_pop_dist": avg_pop_dist,
        "pop_dist_pct" : pop_dist_pct,
        "area_land": updaters.Tally("ALAND10", alias = "area_land"),
        "area_water": updaters.Tally("AWATER10", alias = "area_water"),
        "Perimeter": updaters.Tally("perimeter", alias = "Perimeter"),
        "Area": updaters.Tally("area", alias = "Area")
    }

    num_elections = settings['num_elections']
    election_names = settings['election_names']
    election_columns = settings['election_columns']
    num_steps = settings['num_steps']
    interval = settings['interval']
    pop_tol = settings['pop_tol']
    MC_type = settings['MC_type']
    
    elections = [
        Election(
            election_names[i],
            {"Democratic": election_columns[i][0], "Republican": election_columns[i][1]},
        )
        for i in range(num_elections)
    ]

    election_updaters = {election.name: election for election in elections}

    my_updaters.update(election_updaters)

    initial_partition = Partition(jgraph, "CD", my_updaters) # by typing in "CD," we are saying to put every county into the congressional district that they belong to
    print('computed initial partition')
    ideal_population =  sum(initial_partition["population"].values()) / len(
        initial_partition
    )
    pop_constraint = constraints.within_percent_of_ideal_population(initial_partition, pop_tol)

    compactness_bound = constraints.UpperBound(
        lambda p: len(p["cut_edges"]), 2 * len(initial_partition["cut_edges"])
    )
    
    proposal = partial(
        recom, pop_col=pop_col, pop_target=ideal_population, epsilon=pop_tol, node_repeats=1)
    
    constraints_=[pop_constraint, compactness_bound]
    
    if MC_type == "flip":
        proposal = propose_random_flip
        constraints_=[single_flip_contiguous, pop_constraint, compactness_bound]
        
    chain = MarkovChain(
        proposal=proposal,
        constraints=constraints_,
        accept=always_accept,
        initial_state=initial_partition,
        total_steps=num_steps
    )

    partitions=[] # recording partitions at each step
    for index, part in enumerate(chain):
        if index % interval == 0:
            print('Markov chain step '+str(index))
            partitions += [part]
    if save_part:
        sd.dump_run(settings['partitions_path'], partitions) 
        print('saved partitions to '+ settings['partitions_path'])
    return(partitions)