Source code for gerrychain.proposals.proposals

import random

# from typing import TypeVar
# Partition = TypeVar("Partition")
from ..partition import Partition


[docs]def propose_any_node_flip(partition: Partition) -> Partition: """ Flip a random node (not necessarily on the boundary) to a random part :param partition: The current partition to propose a flip from. :type partition: Partition :returns: A possible next `~gerrychain.Partition` :rtype: Partition """ node = random.choice(tuple(partition.graph)) newpart = random.choice(tuple(partition.parts)) return partition.flip({node: newpart})
[docs]def propose_flip_every_district(partition: Partition) -> Partition: """ Proposes a random boundary flip for each district in the partition. :param partition: The current partition to propose the flips from. :type partition: Partition :returns: A possible next `~gerrychain.Partition` :rtype: Partition """ flips = dict() for dist_edges in partition["cut_edges_by_part"].values(): edge = random.choice(tuple(dist_edges)) index = random.choice((0, 1)) flipped_node, other_node = edge[index], edge[1 - index] flip = {flipped_node: partition.assignment.mapping[other_node]} flips.update(flip) return partition.flip(flips)
[docs]def propose_chunk_flip(partition: Partition) -> Partition: """ Chooses a random boundary node and proposes to flip it and all of its neighbors :param partition: The current partition to propose a flip from. :type partition: Partition :returns: A possible next `~gerrychain.Partition` :rtype: Partition """ flips = dict() edge = random.choice(tuple(partition["cut_edges"])) index = random.choice((0, 1)) flipped_node = edge[index] valid_flips = [ nbr for nbr in partition.graph.neighbors(flipped_node) if partition.assignment.mapping[nbr] != partition.assignment.mapping[flipped_node] ] for flipped_neighbor in valid_flips: flips.update({flipped_neighbor: partition.assignment.mapping[flipped_node]}) return partition.flip(flips)
[docs]def propose_random_flip(partition: Partition) -> Partition: """ Proposes a random boundary flip from the partition. :param partition: The current partition to propose a flip from. :type partition: Partition :returns: A possible next `~gerrychain.Partition` :rtype: Partition """ if len(partition["cut_edges"]) == 0: return partition edge = random.choice(tuple(partition["cut_edges"])) index = random.choice((0, 1)) flipped_node, other_node = edge[index], edge[1 - index] flip = {flipped_node: partition.assignment.mapping[other_node]} return partition.flip(flip)
[docs]def slow_reversible_propose_bi(partition: Partition) -> Partition: """ Proposes a random boundary flip from the partition in a reversible fashion for bipartitions by selecting a boundary node at random and uniformly picking one of its neighboring parts. For k-partitions this is not uniform since there might be multiple parts next to a single node. Temporary version until we make an updater for this set. :param partition: The current partition to propose a flip from. :type partition: Partition :returns: A possible next `~gerrychain.Partition` :rtype: Partition """ b_nodes = {x[0] for x in partition["cut_edges"]}.union( {x[1] for x in partition["cut_edges"]} ) flip = random.choice(list(b_nodes)) neighbor_assignments = list( set( [ partition.assignment.mapping[neighbor] for neighbor in partition.graph.neighbors(flip) ] ) ) neighbor_assignments.remove(partition.assignment.mapping[flip]) flips = {flip: random.choice(neighbor_assignments)} return partition.flip(flips)
flip = propose_random_flip
[docs]def slow_reversible_propose(partition: Partition) -> Partition: """ Proposes a random boundary flip from the partition in a reversible fasion by selecting uniformly from the (node, flip) pairs. Temporary version until we make an updater for this set. :param partition: The current partition to propose a flip from. :type partition: Partition :returns: A possible next `~gerrychain.Partition` :rtype: Partition """ b_nodes = { (x[0], partition.assignment.mapping[x[1]]) for x in partition["cut_edges"] }.union( {(x[1], partition.assignment.mapping[x[0]]) for x in partition["cut_edges"]} ) flip = random.choice(list(b_nodes)) return partition.flip({flip[0]: flip[1]})