Gonality Game Module
Combinatorial tools for chip firing and gonality studies.
This module provides functions for parking functions, independent sets, treewidth calculations, and scramble numbers as mentioned in the academic literature.
- chipfiring.CFCombinatorics.is_parking_function(sequence: List[int], n: int | None = None) bool[source]
Check if a sequence is a parking function.
A parking function of length n is a sequence (a1, a2, …, an) where ai ∈ {1, 2, …, n} such that if we sort the sequence in non-decreasing order to get (b1, b2, …, bn), then bi ≤ i for all i.
- Parameters:
sequence – The sequence to test
n – Length constraint (if None, uses len(sequence))
- Returns:
True if sequence is a parking function
- Return type:
Examples
>>> is_parking_function([1, 1, 2]) True >>> is_parking_function([1, 3, 3]) False >>> is_parking_function([2, 1, 1]) True
- chipfiring.CFCombinatorics.generate_parking_functions(n: int) List[List[int]][source]
Generate all parking functions of length n.
- Parameters:
n – Length of parking functions to generate
- Returns:
All parking functions of length n
- Return type:
List[List[int]]
Examples
>>> funcs = generate_parking_functions(2) >>> len(funcs) 3 >>> sorted(funcs) [[1, 1], [1, 2], [2, 1]]
- chipfiring.CFCombinatorics.parking_function_count(n: int) int[source]
Return the number of parking functions of length n.
The number of parking functions of length n is (n+1)^(n-1).
- Parameters:
n – Length of parking functions
- Returns:
Number of parking functions of length n
- Return type:
Examples
>>> parking_function_count(1) 1 >>> parking_function_count(2) 3 >>> parking_function_count(3) 16
- chipfiring.CFCombinatorics.is_connected(graph: CFGraph) bool[source]
Check if a graph is connected.
- Parameters:
graph – The graph to check
- Returns:
True if graph is connected
- Return type:
- chipfiring.CFCombinatorics.maximal_independent_sets(graph: CFGraph) List[Set[str]][source]
Find all maximal independent sets in a graph.
An independent set is a set of vertices with no edges between them. A maximal independent set cannot be extended by adding another vertex.
- Parameters:
graph – The graph to analyze
- Returns:
List of maximal independent sets (vertex names)
- Return type:
List[Set[str]]
Examples
>>> vertices = {"0", "1", "2"} >>> edges = [("0", "1", 1)] >>> graph = CFGraph(vertices, edges) >>> mis = maximal_independent_sets(graph) >>> len(mis) >= 1 True
- chipfiring.CFCombinatorics.independence_number(graph: CFGraph) int[source]
Compute the independence number (size of largest independent set).
- Parameters:
graph – The graph to analyze
- Returns:
The independence number
- Return type:
Examples
>>> vertices = {"0", "1", "2"} >>> edges = [("0", "1", 1)] >>> graph = CFGraph(vertices, edges) >>> independence_number(graph) >= 1 True
- chipfiring.CFCombinatorics.minimum_degree(graph: CFGraph) int[source]
Compute the minimum degree of a graph.
For connected simple graphs, this provides a lower bound on treewidth and gonality:
δ(G) ≤ tw(G) ≤ gon(G). With parallel edges, this function returns weighted valence and that inequality need not hold.- Parameters:
graph – The graph to analyze
- Returns:
The minimum degree
- Return type:
Examples
>>> vertices = {"0", "1", "2"} >>> edges = [("0", "1", 1), ("1", "2", 1), ("0", "2", 1)] >>> graph = CFGraph(vertices, edges) >>> minimum_degree(graph) 2
- chipfiring.CFCombinatorics.maximum_degree(graph: CFGraph) int[source]
Compute the maximum degree of a graph.
- Parameters:
graph – The graph to analyze
- Returns:
The maximum degree
- Return type:
Examples
>>> vertices = {"0", "1", "2", "3"} >>> edges = [("0", "1", 1), ("1", "2", 1), ("2", "3", 1)] >>> graph = CFGraph(vertices, edges) >>> maximum_degree(graph) 2
- chipfiring.CFCombinatorics.is_bipartite(graph: CFGraph) bool[source]
Check if a graph is bipartite.
- Parameters:
graph – The graph to check
- Returns:
True if the graph is bipartite
- Return type:
Examples
>>> vertices = {"0", "1", "2", "3"} >>> edges = [("0", "2", 1), ("0", "3", 1), ("1", "2", 1), ("1", "3", 1)] >>> graph = CFGraph(vertices, edges) >>> is_bipartite(graph) True
- chipfiring.CFCombinatorics.bramble_order_lower_bound(graph: CFGraph) int[source]
Compute a lower bound on the maximum bramble order.
This uses the relation between bramble order, treewidth, and gonality.
- Parameters:
graph – The graph to analyze
- Returns:
Lower bound on maximum bramble order
- Return type:
Examples
>>> vertices = {"0", "1", "2"} >>> edges = [("0", "1", 1), ("1", "2", 1), ("0", "2", 1)] >>> graph = CFGraph(vertices, edges) >>> bramble_order_lower_bound(graph) >= 1 True
- chipfiring.CFCombinatorics.complete_multipartite_gonality(partition_sizes: List[int]) int[source]
Compute the exact gonality of a complete multipartite graph K_{n1,n2,…,nk}.
For at least two nonempty parts,
gon(K_{n1,...,nk}) = n - max(ni).- Parameters:
partition_sizes – List of partition sizes
- Returns:
The exact gonality
- Return type:
Examples
>>> complete_multipartite_gonality([2, 2, 2]) # Octahedron K_{2,2,2} 4 >>> complete_multipartite_gonality([3, 4]) # K_{3,4} 3
- chipfiring.CFCombinatorics.octahedron_independence_number() int[source]
Compute the independence number of the octahedron (K_{2,2,2}).
As proven in the theory, the octahedron has independence number 2.
- Returns:
The independence number (2)
- Return type:
- chipfiring.CFCombinatorics.octahedron_bramble_construction() Dict[str, Any][source]
Construct the bramble of order 5 on the octahedron as described in the theory.
This bramble proves that the treewidth of the octahedron is at least 4.
- Returns:
Information about the bramble construction
- Return type:
Dict[str, Any]
- chipfiring.CFCombinatorics.treewidth_upper_bound(graph: CFGraph) int[source]
Compute an upper bound for the treewidth of a graph.
This uses a simple greedy elimination ordering to get an upper bound. The actual treewidth may be smaller.
- Parameters:
graph – The graph to analyze
- Returns:
Upper bound on treewidth
- Return type:
Examples
>>> vertices = {"0", "1", "2", "3"} >>> edges = [("0", "1", 1), ("1", "2", 1), ("2", "3", 1), ("3", "0", 1)] >>> graph = CFGraph(vertices, edges) >>> treewidth_upper_bound(graph) >= 1 True
- chipfiring.CFCombinatorics.scramble_number_upper_bound(graph: CFGraph) int[source]
Return the trivial vertex-count upper bound for scramble number.
- Parameters:
graph – The graph to analyze
- Returns:
Upper bound on scramble number
- Return type:
Examples
>>> vertices = {"0", "1", "2"} >>> edges = [("0", "1", 1), ("1", "2", 1)] >>> graph = CFGraph(vertices, edges) >>> scramble_number_upper_bound(graph) >= 1 True
- chipfiring.CFCombinatorics.genus_upper_bound(graph: CFGraph) int[source]
Return the chip-firing genus (first Betti number) of a connected graph.
The historical function name is retained for compatibility; the returned value is exact, not merely an upper bound.
- Parameters:
graph – The graph to analyze
- Returns:
Upper bound on genus
- Return type:
Examples
>>> vertices = {"0", "1", "2", "3"} >>> edges = [("0", "1", 1), ("1", "2", 1), ("2", "3", 1), ("3", "0", 1)] >>> graph = CFGraph(vertices, edges) >>> genus_upper_bound(graph) >= 0 True
- chipfiring.CFCombinatorics.gonality_theoretical_bounds(graph: CFGraph) Dict[str, int][source]
Compute certified divisorial-gonality bounds for a connected simple graph.
The lower bounds use vertex connectivity, minimum degree, and bramble order. The upper bounds use the vertex count, independence number, and the graph Riemann-Roch bound
g + 1. Multigraphs are rejected because the simple-graph independence and treewidth inequalities used here do not account for edge multiplicity.- Parameters:
graph – The graph to analyze
- Returns:
Dictionary of bound names to values
- Return type:
Examples
>>> vertices = {"0", "1", "2", "3"} >>> edges = [("0", "1", 1), ("1", "2", 1), ("2", "3", 1), ("3", "0", 1)] >>> graph = CFGraph(vertices, edges) >>> bounds = gonality_theoretical_bounds(graph) >>> 'independence_upper_bound' in bounds True
- chipfiring.CFCombinatorics.analyze_graph_properties(graph: CFGraph) Dict[str, Any][source]
Analyze various combinatorial properties relevant to gonality.
- Parameters:
graph – The graph to analyze
- Returns:
Dictionary of properties and their values
- Return type:
Dict[str, Any]
Examples
>>> vertices = {"0", "1", "2"} >>> edges = [("0", "1", 1), ("1", "2", 1)] >>> graph = CFGraph(vertices, edges) >>> props = analyze_graph_properties(graph) >>> 'num_vertices' in props True
- chipfiring.CFCombinatorics.graph_complement(graph: CFGraph) CFGraph[source]
Compute the complement of a graph.
- Parameters:
graph – The input graph
- Returns:
The complement graph
- Return type:
- chipfiring.CFCombinatorics.icosahedron_independence_number() int[source]
Compute the independence number of the icosahedron.
The icosahedron has independence number α(I) = 3.
- Returns:
The independence number (3)
- Return type:
- chipfiring.CFCombinatorics.icosahedron_2_uniform_scramble() Dict[str, Any][source]
Return the all-edges 2-uniform scramble on the icosahedron.
Beougher et al., “Chip-firing on the Platonic solids: a primer for studying graph gonality,” use all 30 edges as the connected two-vertex eggs. Its hitting number is 9 and its egg-cut number is 8, so its norm is 8.
- Returns:
Dict containing scramble construction details
- chipfiring.CFCombinatorics.icosahedron_screewidth_bound() Dict[str, int][source]
Return the known scramble-number and screewidth values for the icosahedron.
The all-edge scramble gives
sn(I) >= 8. A width-8 tree-cut decomposition givesscw(I) <= 8, andsn(I) <= scw(I), so both parameters equal 8.- Returns:
Dict containing screewidth bounds
- chipfiring.CFCombinatorics.icosahedron_subgraph_outdegree_bounds() Dict[str, Any][source]
Compute edge-boundary minima for vertex subsets of the icosahedron.
The reference lower bounds are 8 for subset orders 2 and 10, and 9 for orders 3 through 9. This function exhaustively computes the actual minimum cut size for every nontrivial subset order and verifies those bounds directly.
- Returns:
Dictionary containing actual and reference lower bounds by subset size.
- chipfiring.CFCombinatorics.icosahedron_gonality_proof_summary() Dict[str, Any][source]
Return a literature-backed summary of the gonality-9 result.
This function does not execute an exhaustive Dhar calculation. It records the published upper- and lower-bound statements so callers can distinguish reference data from values computed by this package.
- Returns:
Dictionary containing the exact published value and proof methods.
- chipfiring.CFCombinatorics.icosahedron_lemma_3_subgraph_bounds() Dict[str, Any][source]
Deprecated compatibility wrapper for subgraph outdegree data.
- chipfiring.CFCombinatorics.icosahedron_dhars_burning_algorithm() Dict[str, Any][source]
Deprecated compatibility wrapper for the published proof summary.
- chipfiring.CFCombinatorics.icosahedron_egg_cut_number() Dict[str, Any][source]
Compute the egg-cut number for the icosahedron.
The egg-cut number is related to scramble theory and provides another perspective on gonality bounds.
- Returns:
Dict containing egg-cut number analysis
- chipfiring.CFCombinatorics.icosahedron_hitting_set_analysis() Dict[str, Any][source]
Analyze hitting sets for the icosahedron scramble construction.
This implements the hitting set computations that appear in the scramble number analysis.
- Returns:
Dict containing hitting set analysis
- chipfiring.CFCombinatorics.icosahedron_gonality_theoretical_bounds() Dict[str, Any][source]
Return literature-backed invariants and exact gonality of the icosahedron.
- Returns:
Dict containing all theoretical bounds
Gonality calculation and gonality games for chip-firing graphs.
This module provides functionality for computing graph gonality and playing gonality games, based on the mathematical framework described in “Chip-firing on the Platonic solids: A primer for studying graph gonality” by Beougher et al.
The gonality of a graph G, denoted gon(G), is the minimum number of chips Player A needs to guarantee a win in the Gonality Game, regardless of where Player B places the -1 chip.
- class chipfiring.CFGonality.GonalityGameResult(player_a_wins: bool, initial_placement: CFDivisor, player_b_placement: str, final_divisor: CFDivisor, winnability: bool, winning_sequence: List[str] | None = None)[source]
Bases:
objectRepresents the result of a single gonality game instance.
- Variables:
player_a_wins (bool) – True if Player A wins, False if Player B wins
initial_placement (CFDivisor) – Player A’s initial chip placement
player_b_placement (str) – Vertex name where Player B placed the -1 chip
final_divisor (CFDivisor) – The divisor after Player B’s move
winnability (bool) – Whether the final divisor is winnable via chip-firing
winning_sequence (Optional[List[str]]) – Sequence of vertices fired to win (if applicable)
- class chipfiring.CFGonality.GonalityResult[source]
Bases:
objectRepresents the result of a gonality calculation.
- Variables:
gonality (int) – The computed gonality value
winning_strategies (List[CFDivisor]) – List of N-chip placements that guarantee Player A wins
logs (List[str]) – Detailed logs of the calculation process
verification_games (Dict[int, List[GonalityGameResult]]) – Game results for verification
- class chipfiring.CFGonality.CFGonality(graph: CFGraph)[source]
Bases:
objectMain class for gonality calculations and gonality games.
- __init__(graph: CFGraph)[source]
Initialize gonality calculator for a given graph.
- Parameters:
graph – The CFGraph to analyze
- play_gonality_game(n_chips: int, player_a_placement: CFDivisor, player_b_vertex: str, verbose: bool = False) GonalityGameResult[source]
Play a single instance of the Gonality Game.
- Parameters:
n_chips – Number of chips Player A is allowed to place
player_a_placement – Player A’s chip placement (must have total degree n_chips)
player_b_vertex – Vertex name where Player B places the -1 chip
verbose – Whether to include detailed winning sequence
- Returns:
Complete result of the game instance
- Return type:
- Raises:
ValueError – If player_a_placement doesn’t have exactly n_chips total degree
- _find_winning_sequence(divisor: CFDivisor) List[str][source]
Find a sequence of chip-firing moves that wins the Dollar Game. This is a simplified implementation - a full implementation would use more sophisticated algorithms.
- test_n_chip_strategy(n_chips: int, placement: CFDivisor) Tuple[bool, List[str]][source]
Test if a given N-chip placement guarantees Player A wins against all possible Player B moves.
- Parameters:
n_chips – Number of chips (for validation)
placement – Player A’s chip placement strategy
- Returns:
Tuple of (strategy_works, losing_vertices) where strategy_works is True if the placement beats all Player B responses, and losing_vertices lists vertices where Player B can place -1 to win
- find_all_n_chip_strategies(n_chips: int, max_strategies: int | None = None) List[CFDivisor][source]
Find all N-chip placements that guarantee Player A wins the Gonality Game.
- Parameters:
n_chips – Number of chips Player A can place
max_strategies – Maximum number of strategies to find (None for all)
- Returns:
List of winning CFDivisor placements
- compute_gonality(max_gonality: int | None = None, find_strategies: bool = True) GonalityResult[source]
Compute the gonality of the graph.
The gonality is the minimum number N such that Player A has a winning strategy in the Gonality Game with N chips.
- Parameters:
max_gonality – Maximum gonality to check (defaults to number of vertices)
find_strategies – Whether to find and store winning strategies
- Returns:
Complete result including gonality value and winning strategies
- Return type:
- verify_gonality_bounds(suspected_gonality: int) Tuple[bool, bool, List[str]][source]
Verify gonality bounds by checking that suspected_gonality works but suspected_gonality-1 doesn’t.
- Parameters:
suspected_gonality – The suspected gonality value to verify
- Returns:
Tuple of (upper_bound_verified, lower_bound_verified, messages) where upper_bound_verified means suspected_gonality works, and lower_bound_verified means suspected_gonality-1 doesn’t work
- chipfiring.CFGonality.gonality(graph: CFGraph, max_gonality: int | None = None, find_strategies: bool = True) GonalityResult[source]
Compute the gonality of a graph.
The gonality of a graph G is the minimum number of chips Player A needs to guarantee winning the Gonality Game, regardless of Player B’s strategy.
Algorithm: 1. For N = 1, 2, 3, …, find all possible ways Player A can place N chips 2. For each placement, test if Player A wins against all possible Player B responses 3. Return the minimum N for which Player A has a guaranteed winning strategy
- Parameters:
graph – The CFGraph to analyze
max_gonality – Maximum gonality to check (defaults to number of vertices)
find_strategies – Whether to find and return winning strategies
- Returns:
Object containing gonality value, winning strategies, and logs
- Return type:
Example
>>> from chipfiring import CFGraph, gonality >>> # Create a simple triangle graph >>> vertices = {"A", "B", "C"} >>> edges = [("A", "B", 1), ("B", "C", 1), ("A", "C", 1)] >>> graph = CFGraph(vertices, edges) >>> result = gonality(graph) >>> result.gonality 2 >>> len(result.winning_strategies) 5
- chipfiring.CFGonality.play_gonality_game(graph: CFGraph, n_chips: int, player_a_placement: CFDivisor, player_b_vertex: str, verbose: bool = False) GonalityGameResult[source]
Play a single instance of the Gonality Game.
Game Rules: 1. Player A places n_chips on the vertices of the graph 2. Player B places -1 chip on any vertex 3. Player A wins if they can eliminate all debt through chip-firing moves
- Parameters:
graph – The CFGraph on which to play
n_chips – Number of chips Player A is allowed
player_a_placement – Player A’s chip placement
player_b_vertex – Vertex where Player B places -1 chip
verbose – Whether to include detailed winning information
- Returns:
Complete result of the game
- Return type:
Example
>>> from chipfiring import CFGraph, CFDivisor, play_gonality_game >>> vertices = {"A", "B", "C"} >>> edges = [("A", "B", 1), ("B", "C", 1), ("A", "C", 1)] >>> graph = CFGraph(vertices, edges) >>> placement = CFDivisor(graph, [("A", 2), ("B", 0), ("C", 0)]) >>> result = play_gonality_game(graph, 2, placement, "B") >>> result.player_a_wins True
Enhanced Dhar’s burning algorithm specifically optimized for gonality games.
This module extends the standard Dhar’s burning algorithm with specialized functions for gonality calculations, including optimizations for finding winning strategies and determining gonality bounds efficiently.
- class chipfiring.CFGonalityDhar.GonalityDharAlgorithm(graph: CFGraph, initial_divisor: CFDivisor, q_name: str)[source]
Bases:
DharAlgorithmEnhanced Dhar’s algorithm specialized for gonality game computations.
This class extends the standard DharAlgorithm with methods specifically designed for efficiency in gonality calculations, including batch testing of strategies and optimized burning processes.
- __init__(graph: CFGraph, initial_divisor: CFDivisor, q_name: str)[source]
Initialize the enhanced Dhar algorithm for gonality games.
- Parameters:
graph – A CFGraph object representing the graph
initial_divisor – A CFDivisor object representing the initial chip configuration
q_name – The name of the distinguished vertex (fire source)
- test_strategy_batch(strategies: List[List[str]]) List[bool][source]
Test multiple strategies efficiently using cached burning results.
- Parameters:
strategies – List of strategies, where each strategy is a list of vertex names
- Returns:
Results for each strategy (True if winning, False otherwise)
- Return type:
List[bool]
- test_strategy(strategy: List[str]) bool[source]
Test if a given strategy is winning. A strategy is winning if, after placing chips according to the strategy and having Player B place -1 at q, the resulting configuration is winnable using the same criterion as the EWD algorithm.
- Parameters:
strategy – List of vertex names representing the strategy (chips added to V-{q})
- Returns:
True if the strategy is winning, False otherwise
- Return type:
- _enhanced_burning(config: CFConfig) Set[str][source]
Enhanced burning algorithm optimized for gonality calculations.
- Parameters:
config – CFConfig object with the chip configuration
- Returns:
Names of all burnt vertices (excluding q)
- Return type:
Set[str]
- _should_burn(vertex: Vertex, burnt_vertices: Set[str], config: CFConfig) bool[source]
Determine if a vertex should burn given current burnt set.
- Parameters:
vertex – The vertex to test
burnt_vertices – Set of currently burnt vertex names
config – The chip configuration
- Returns:
True if vertex should burn
- Return type:
- _config_to_tuple(config: CFConfig) tuple[source]
Convert a configuration to a hashable tuple for caching.
- Parameters:
config – CFConfig object
- Returns:
Hashable representation of the configuration
- Return type:
- find_minimal_winning_strategies(max_chips: int) List[List[str]][source]
Find all minimal winning strategies using at most max_chips chips.
- Parameters:
max_chips – Maximum number of chips to use
- Returns:
List of minimal winning strategies
- Return type:
List[List[str]]
- _is_subset_multiset(subset: List[str], superset: List[str]) bool[source]
Check if one multiset is a subset of another.
- Parameters:
subset – Potential subset as list
superset – Potential superset as list
- Returns:
True if subset is a subset of superset
- Return type:
- chipfiring.CFGonalityDhar.enhanced_dhar_gonality_test(graph: CFGraph, q_vertex_name: str, max_gonality: int | None = None) Tuple[int, List[List[str]]][source]
Use enhanced Dhar’s algorithm to compute gonality and find winning strategies. This computes the smallest k such that placing k chips on V-{q} results in a configuration that is winnable after -1 chip is placed on q.
- chipfiring.CFGonalityDhar.batch_gonality_analysis(graphs: List[Tuple[CFGraph, str]], max_gonality: int | None = None) Dict[str, Dict][source]
Analyze gonality for multiple graphs efficiently.
- Parameters:
graphs – List of (graph, q_vertex_name) pairs
max_gonality – Maximum gonality to test for each graph
- Returns:
Results for each graph
- Return type:
Dict[str, Dict]