import numpy as np from functools import partial import json import csv import math import pickle import matplotlib.pyplot as plt from gerrychain.random import random from gerrychain import Graph, Partition, Election, MarkovChain, GeographicPartition, accept, constraints from gerrychain.updaters import Tally, cut_edges, county_splits, Tally, boundary_nodes, cut_edges_by_part, exterior_boundaries, interior_boundaries, perimeter from gerrychain.constraints import single_flip_contiguous, Validator, within_percent_of_ideal_population, refuse_new_splits from gerrychain.proposals import recom from gerrychain.accept import always_accept from gerrychain.tree import recursive_tree_part from gerrychain.metrics.compactness import compute_polsby_popper, polsby_popper random.seed(20210809) np_load_old = np.load np.load = lambda *a,**k: np_load_old(*a, allow_pickle=True, **k) ## ## ## ## ## ## ## ## ## ## ## ## set-up argparse! ## ## ## ## ## ## ## ## ## ## ## parser = argparse.ArgumentParser(description="MO ensemble", prog="sampling.py") parser.add_argument("map", metavar="map", type=str, choices=["state_house", "state_senate"], help="the map to redistrict") parser.add_argument("eps", metavar="epsilon", type=float, # choices=[0.01, 0.03, 0.05, .08],
help="the number of plans to sample") parser.add_argument( "popcol", metavar="population column", type=str, choices=["TOTPOP", "VAP", "CPOP", "CVAP"], help="the population column by which to balance redistricting") parser.add_argument("--i", metavar="run number", type=int, default=0, help="which chain run is this?") args = parser.parse_args() from gerrychain.random import random random.seed(args.i) from gerrychain import Graph, GeographicPartition, Partition, Election, accept from gerrychain.updaters import Tally, cut_edges from gerrychain import MarkovChain from gerrychain.proposals import recom from gerrychain.accept import always_accept from gerrychain import constraints from gerrychain.tree import recursive_tree_part num_districts_in_map = { "congress": 14, "congress_2000": 13, "state_senate": 56, "state_house": 180 }
def generator(stop_event, partition_queue, _type, step_count=1000, burn_in=1000): """ Creates and runs generator for a proposal type. Parameters ---------- _type : string either "chunk" or "random" step_count : int, Default 1000 steps of chain to run (after burn-in) burn_in : int, Default 1000 steps to burn-in for (not to collect data) stop_event: multiprocessing.Event tells chain's workers if generation has stopped partition_queue: multiprocessing.Queue structure that takes each partition as it is generated """ # FOR REPRODUCIBILITY from gerrychain.random import random random.seed(2020) init_partition = Partition( graph, assignment=race_matrix.to_dict()["partition"], updaters={"population": Tally("population")}, ) if _type == "chunk": chain = MarkovChain( proposal=propose_chunk_flip, constraints=is_valid, accept=always_accept, initial_state=init_partition, total_steps=step_count + burn_in, ) elif _type == "random": chain = MarkovChain( proposal=propose_random_flip, constraints=is_valid, accept=always_accept, initial_state=init_partition, total_steps=step_count + burn_in, ) else: raise ValueError("Wrong chain type given. Give 'chunk' or 'random'.") iter(chain) if _type == "chunk": burn_bar = trange(burn_in, desc=f"{_type} flip Burn-in", leave=True, position=0) pbar = trange(step_count, desc=f"Generating {_type} flip", leave=True, position=0) else: burn_bar = trange(burn_in, desc=f"{_type} flip Burn-in", leave=True, position=1) pbar = trange(step_count, desc=f"Generating {_type} flip", leave=True, position=1) # burn-in for _ in burn_bar: next(chain) for i in pbar: partition_queue.put((i, dict(next(chain).assignment))) stop_event.set() # # send a text when done (SEE FIELDS) # client.messages.create( # to=<YOUR PHONE NUMBER>, # from_=<TWILIO SOUCE NUMBER>, # body=f"{_type.capitalize()} flip for {CITY_NAME} completed.", # ) print(f"{_type.capitalize()} Generator: {stop_event.is_set()}")
def generator( stop_event, partition_queue, step_count=1000, burn_in_ratio=0.1, thinning=5, seed=2020, ): """ Creates and runs generator of map proposals Parameters ---------- step_count : int, Default 1000 steps of chain to run (after burn-in) burn_in_ratio : float, Default 0.1 steps to burn-in for, as a ratio of the total step count (not to collect data) stop_event: multiprocessing.Event tells chain's workers if generation has stopped partition_queue: multiprocessing.Queue structure that takes each partition as it is generated thinning: int, Default 5 Take every <thinning>th result from the chain to minimize dependence seed: int, Default 2020 Random seed for reproducibility """ # FOR REPRODUCIBILITY from gerrychain.random import random random.seed(seed) init_partition = Partition( graph, assignment=race_matrix.to_dict()["partition"], updaters={"population": Tally("population")}, ) chain = MarkovChain( proposal=propose_chunk_flip, constraints=is_valid, accept=always_accept, initial_state=init_partition, total_steps=step_count + burn_in_ratio * step_count, ) iter(chain) burn_bar = trange(int(burn_in_ratio * step_count), desc=f"Burn-in", leave=True, position=0) pbar = trange( int(burn_in_ratio * step_count) + step_count, desc=f"Generating maps", leave=True, position=0, ) # burn-in # for _ in burn_bar: # next(chain) for i in pbar: map_proposal = (i, dict(next(chain).assignment)) # only push proposal to queue if it is <thinning>th proposal if i % thinning == 0: partition_queue.put(map_proposal) stop_event.set() # # send a text when done (SEE FIELDS) # client.messages.create( # to=<YOUR PHONE NUMBER>, # from_=<TWILIO SOUCE NUMBER>, # body=f"{_type.capitalize()} flip for {CITY_NAME} completed.", # ) print(f"{CITY_NAME} Generator: {stop_event.is_set()}")
import argparse import geopandas as gpd import pandas as pd import matplotlib.pyplot as plt from gerrychain.random import random random.seed(20210511) from gerrychain import Graph, Partition, Election, MarkovChain, GeographicPartition, accept, constraints from gerrychain.updaters import Tally, cut_edges from gerrychain.constraints import single_flip_contiguous, Validator, within_percent_of_ideal_population, refuse_new_splits from gerrychain.proposals import recom from gerrychain.accept import always_accept from gerrychain.tree import recursive_tree_part import numpy as np from functools import partial import json import csv import pickle ## ## ## ## ## ## ## ## ## ## ## ## set-up argparse! ## ## ## ## ## ## ## ## ## ## ## parser = argparse.ArgumentParser(description="MO ensemble", prog="sampling.py") parser.add_argument("map", metavar="map", type=str, choices=["state_house", "state_senate"], help="the map to redistrict") parser.add_argument("eps", metavar="epsilon",
# FOR REPRODUCIBILITY import time from gerrychain.random import random random.seed(2020) import os import argparse from twilio.rest import Client import geopandas as gpd import matplotlib.pyplot as plt import networkx as nx import numpy as np import pandas as pd import seaborn as sns from gerrychain import ( GeographicPartition, Graph, MarkovChain, Partition, accept, constraints, proposals, updaters, ) from gerrychain.accept import always_accept from gerrychain.constraints import ( LowerBound, UpperBound, Validator, WithinPercentRangeOfBounds,