API Reference

MutationGame

class mutation_game.MutationGame(adj_matrix)

Bases: object

calculate_roots()

Compute the root system by applying all possible mutation sequences starting from each simple root (standard basis vector e_i).

Requires a finite-type graph (positive definite Cartan matrix).

Returns:

list of numpy arrays representing the distinct roots

Return type:

roots

cartan_eigenvalues()

Return the eigenvalues of the symmetrized Cartan form, sorted ascending.

cartan_eigenvectors()

Return the eigenvalues and eigenvectors of the symmetrized Cartan form.

Returns a tuple (eigenvalues, eigenvectors) where eigenvalues is a 1-D array sorted ascending and eigenvectors is a 2-D array whose column i is the eigenvector for eigenvalues[i].

cartan_matrix()

Return the generalized Cartan matrix C = 2I - A^T.

For simple graphs (symmetric A), this is the same as 2I - A. For directed multigraphs, A^T is used because the mutation at node k depends on the incoming edges (column k of A).

find_mutation_path(source, target)

Find a shortest sequence of mutations transforming source into target.

Parameters:
  • source – root vector (list or array)

  • target – root vector (list or array)

Returns:

A list of (mutation_index, resulting_vector) pairs representing each step. Returns an empty list if source == target.

Raises:

ValueError – if source or target is not in the root system, or no path exists between them.

classmethod from_dynkin(name)

Create a MutationGame from a Dynkin diagram name.

Supported types:
Simply-laced (symmetric adjacency):

A_n (n >= 1): path graph D_n (n >= 4): path with fork at one end E_6, E_7, E_8: exceptional diagrams

Non-simply-laced (directed multigraph):

B_n (n >= 2): path with (2,1) edge at one end C_n (n >= 3): path with (1,2) edge at one end F_4: 4 nodes with (2,1) in the middle G_2: 2 nodes with (3,1) edge

Note: B/C notation follows Wildberger’s convention (based on the directed multigraph structure), which is swapped relative to Bourbaki.

Examples: “A3”, “D5”, “E6”, “B3”, “C4”, “F4”, “G2”

is_finite_type()

Check whether the root system is finite.

For symmetric Cartan matrices (ADE), checks positive definiteness directly. For non-symmetric cases (BCFG), checks the symmetrized form D @ C.

mutate(node_idx)

Apply the mutation at node_idx as a matrix multiplication.

The mutation matrix M_k uses incoming edges (column k of A):

M_k[k, j] = A[j, k] for j != k M_k[k, k] = -1

This gives: new[k] = -old[k] + sum_j A[j,k] * old[j] For simple graphs (symmetric A), this reduces to the standard rule. For directed multigraphs, each neighbor j contributes A[j,k] copies of its population (one per incoming edge from j to k).

mutation_matrix(node_idx)

Return the mutation matrix for a given node index.

mutation_path_table(positive_only=True)

Build a table of shortest mutation paths between all pairs of roots.

Parameters:

positive_only – if True (default), only include positive roots

Returns:

A list of dicts with keys ‘source’, ‘target’, ‘path’, ‘length’. ‘path’ is a list of mutation indices.

plot_root_orbits(positive_only=True)

Build and display the mutation graph of the root system.

Each node is a root vector; an edge connects two roots that differ by a single mutation, labeled with the mutation index.

Parameters:

positive_only – if True (default), show only positive roots with simple roots aligned at the top

Requires: pip install networkx matplotlib

print_mutation_path_table(positive_only=True)

Print the mutation path table in a formatted layout.

set_starting_population(node_values)

Initializes the cities with specific populations.

Singularity Analysis

Tools for computing invariants and coordinate changes in singularity theory, connecting the ADE classification to Dynkin diagrams. See From Singularities to Dynkin Diagrams for the mathematical background.

mutation_game.milnor_number(f, variables)

Compute the Milnor number of an isolated singularity at the origin.

Uses the resultant method for two-variable singularities and the local algebra dimension for the general case.

Parameters:
  • f – sympy expression for the function germ

  • variables – tuple/list of sympy symbols (the variables)

Returns:

the Milnor number mu

Return type:

int

Examples

>>> from sympy import symbols
>>> x, y = symbols('x y')
>>> milnor_number(x**3 + y**2, (x, y))
2
>>> milnor_number(x**2 * y + y**4, (x, y))
5
mutation_game.corank(f, variables)

Compute the corank of a singularity at the origin.

The corank is the number of zero eigenvalues of the Hessian matrix, equivalently n - rank(H).

Parameters:
  • f – sympy expression

  • variables – tuple/list of sympy symbols

Returns:

the corank

Return type:

int

mutation_game.classify(f, variables)

Classify a simple singularity by its ADE type.

Uses the Milnor number and corank to determine the type.

Parameters:
  • f – sympy expression

  • variables – tuple/list of sympy symbols

Returns:

the ADE type (e.g. “A3”, “D5”, “E6”) or “unknown”

Return type:

str

mutation_game.splitting_lemma(f, variables)

Apply the Splitting Lemma to separate non-degenerate directions.

Returns the coordinate substitution and the reduced function.

Parameters:
  • f – sympy expression

  • variables – tuple/list of sympy symbols

Returns:

‘substitution’: dict mapping old vars to expressions in new vars ‘quadratic_part’: the non-degenerate quadratic part ‘residual’: the reduced function in fewer variables ‘corank’: corank of the singularity ‘new_variables’: list of new variable symbols

Return type:

dict with keys

mutation_game.jet_reduce(f, variable, target_degree, max_order=10)

Reduce a one-variable singularity to its normal form by eliminating higher-order terms via polynomial coordinate changes.

Parameters:
  • f – sympy expression in one variable

  • variable – the sympy symbol

  • target_degree – the degree of the leading term (e.g. 3 for A_2)

  • max_order – maximum order to eliminate

Returns:

‘normal_form’: the reduced function (truncated) ‘coordinate_change’: expression for old variable in terms of new ‘steps’: list of (order, coefficient_killed, parameter_value)

Return type:

dict with keys

mutation_game.homotopy_equivalence(f, g, variables)

Construct the coordinate change between two equivalent singularities using Moser’s path method.

Connects f and g by F_t = (1-t)*f + t*g and integrates the flow. Currently supports cases where the velocity field ODE can be solved in closed form.

Parameters:
  • f – sympy expressions (equivalent singularities)

  • g – sympy expressions (equivalent singularities)

  • variables – tuple/list of sympy symbols

Returns:

‘coordinate_change’: dict mapping each variable to its image ‘velocity_field’: the vector field (a_1, …, a_n) ‘F_t’: the homotopy path

Return type:

dict with keys