Source code for gerrychain.meta.diversity

"""
Simple tooling to collect diversity stats on chain runs
"""

from collections.abc import Hashable, Iterable, Iterator
from dataclasses import dataclass

from gerrychain.partition import Partition


[docs] @dataclass class DiversityStats: """ Lightweight stats object that reports the diversity of a given chain. Attributes: unique_plans (int): The number of unique plans seen so far. unique_districts (int): The number of unique districts seen so far. steps_taken (int): The number of steps taken so far. Example usage:: DiversityStats(unique_plans=44162, unique_districts=82992, steps_taken=100000) """ unique_plans: int unique_districts: int steps_taken: int
[docs] def collect_diversity_stats( chain: Iterable[Partition], ) -> Iterator[tuple[Partition, DiversityStats]]: """Report the diversity of the chain being run, live, as a drop-in wrapper. Requires the cut_edges updater on each `Partition` object. Plans/districts are considered distinct if they are not isomorphic. That is, relabled plans and districts are considered non-unique and counted as duplicate. Example usage:: for partition, stats in collect_diversity_stats( Replay( graph, "sample-run.chain" ) ): print(stats) # normal chain stuff here Args: chain (Iterable[Partition]): A chain object to collect stats on. Returns: Iterator[tuple[Partition, DiversityStats]]: Pairs of partitions and cumulative statistics. """ seen_plans: set[frozenset[frozenset[Hashable]]] = set() seen_districts: set[frozenset[Hashable]] = set() unique_plans = 0 unique_districts = 0 steps_taken = 0 for partition in chain: steps_taken += 1 for _, nodes in partition.assignment.parts.items(): hashable_nodes = frozenset(nodes) if hashable_nodes not in seen_districts: unique_districts += 1 seen_districts.add(hashable_nodes) cut_edges = partition["cut_edges"] hashable_cut_edges = frozenset(frozenset(edge) for edge in cut_edges) if hashable_cut_edges not in seen_plans: unique_plans += 1 seen_plans.add(hashable_cut_edges) stats = DiversityStats( unique_plans=unique_plans, unique_districts=unique_districts, steps_taken=steps_taken, ) yield partition, stats