qig.dynamics

Constrained maximum entropy production dynamics.

Constrained dynamics and GENERIC-like structure for the quantum inaccessible game.

This module provides the InaccessibleGameDynamics class, which implements constrained steepest-entropy-ascent dynamics in natural-parameter space, with support for different time parametrisations.

class qig.dynamics.InaccessibleGameDynamics(exp_family, method='duhamel')[source]

Bases: object

Constrained maximum entropy production dynamics.

Implements: θ̇ = -Π_∥(θ) G(θ) θ where Π_∥ projects onto constraint manifold ∑_i h_i = C.

Primary API

solve(theta_0, n_steps, dt, …)Recommended method for integrating dynamics.

Uses gradient descent with Newton projection onto constraint manifold. Supports entropy time via entropy_time=True.

Advanced/Internal

flow(t, theta) : Compute θ̇ at a single point. For custom integrators.

Example

>>> from qig.exponential_family import QuantumExponentialFamily
>>> from qig.dynamics import InaccessibleGameDynamics
>>>
>>> exp_family = QuantumExponentialFamily(n_pairs=1, d=3, pair_basis=True)
>>> theta_0 = exp_family.get_bell_state_parameters(epsilon=0.01)
>>>
>>> dynamics = InaccessibleGameDynamics(exp_family)
>>> result = dynamics.solve(theta_0, n_steps=100, dt=0.01)
>>>
>>> print(f"Converged: {result['converged']}")
>>> print(f"Constraint preserved: dC = {result['constraint_values'][-1] - result['C_init']:.2e}")
__init__(exp_family, method='duhamel')[source]

Initialise dynamics for given exponential family.

Parameters:
  • exp_family (QuantumExponentialFamily) – The exponential family to integrate dynamics for

  • method (str, optional) – Method for computing ∂ρ/∂θ: ‘duhamel’ (accurate, slow) or ‘sld’ (fast, ~5% error) Default: ‘duhamel’

set_time_mode(mode)[source]

Set time parametrisation mode.

Parameters:

mode (str) – ‘affine’ : standard ODE time τ ‘entropy’ : entropy time t where dH/dt = 1 ‘real’ : physical time (reserved for unitary part)

Return type:

None

flow(t, theta)[source]

Compute θ̇ = -Π_∥ G θ at given θ (advanced/internal use).

This is a low-level method that computes the flow vector at a single point. For most use cases, prefer solve() which handles integration and constraint projection automatically.

Parameters:
  • t (float) – Time (used for time-dependent problems; ignored for autonomous flow)

  • theta (ndarray) – Natural parameters at which to compute the flow

Returns:

theta_dot – The constrained flow vector θ̇ = -Π_∥ G θ

Return type:

ndarray

Notes

If time_mode=’entropy’, the flow is scaled so dH/dt = 1.

solve(theta_0, n_steps=1000, dt=0.001, convergence_tol=1e-06, entropy_time=False, project=True, project_every=10, verbose=True)[source]

Solve constrained maximum entropy dynamics (recommended method).

Uses gradient descent with Newton projection onto constraint manifold. This is the primary API for integrating the inaccessible game dynamics.

Parameters:
  • theta_0 (ndarray) – Initial natural parameters

  • n_steps (int, default 1000) – Maximum number of steps

  • dt (float, default 0.001) – Step size (or entropy increment if entropy_time=True)

  • convergence_tol (float, default 1e-6) – Stop when ||F|| < convergence_tol

  • entropy_time (bool, default False) – If True, scale steps so dH/dt = 1 (entropy increases by dt per step)

  • project (bool, default True) – Project onto constraint manifold (recommended)

  • project_every (int, default 10) – Project every N steps (for efficiency)

  • verbose (bool, default True) – Print progress messages

Returns:

trajectoryndarray, shape (n_steps+1, n_params)

Parameter trajectory θ(t)

flow_normsndarray

||F(θ)|| at each step (→ 0 at convergence)

constraint_valuesndarray

Σᵢ hᵢ at each step (should stay ≈ constant)

C_initfloat

Initial constraint value

convergedbool

Whether convergence was achieved

n_stepsint

Number of steps taken

Return type:

dict with keys

Example

>>> result = dynamics.solve(theta_0, n_steps=500, dt=0.01, entropy_time=True)
>>> print(f"Converged: {result['converged']}")
integrate(theta_0, t_span, n_points=100)[source]

[DEPRECATED] Integrate using scipy solve_ivp.

Deprecated since version This: method does not project onto the constraint manifold, causing constraint drift. Use solve() instead.

Warning

This method is numerically unstable for constrained problems. The constraint C = Σᵢ hᵢ will drift over time, giving incorrect results. Use solve() which includes Newton projection for stability.

Return type:

Dict[str, Any]

Parameters:
solve_constrained_maxent(theta_init, n_steps=1000, dt=0.001, convergence_tol=1e-06, project=True, project_every=10, use_entropy_time=False)[source]

Solve constrained maximum entropy dynamics using gradient descent with projection.

  • Uses gradient descent to maximise joint entropy

  • Projects onto constraint manifold at each step

  • Much more stable than ODE integration for constrained optimisation

Dynamics: dθ/dt = F(θ) = -Π_∥(θ) G(θ) θ where Π_∥ projects onto Σᵢ hᵢ(θ) = C

Parameters:
  • theta_init (array) – Initial parameter vector

  • n_steps (int) – Maximum number of gradient steps

  • dt (float) – Step size for gradient descent

  • convergence_tol (float) – Stop when ||F|| < convergence_tol

  • project (bool) – Whether to project onto constraint manifold

  • project_every (int) – Project onto constraint manifold every N steps (for efficiency)

  • use_entropy_time (bool) – If True, scale step size so that entropy increases by dt per step

Returns:

trajectoryarray, shape (n_steps, n_params)

Parameter trajectory θ(t)

flow_normsarray

||F(θ)|| at each step

constraint_valuesarray

Σᵢ hᵢ at each step (should be ≈ constant)

convergedbool

Whether convergence criterion was met

C_initfloat

Initial constraint value

Return type:

dict with keys

Parameters:
class qig.dynamics.GenericDynamics(exp_family, structure_constants=None, method='duhamel')[source]

Bases: InaccessibleGameDynamics

GENERIC-aware dynamics for the quantum inaccessible game.

Extends InaccessibleGameDynamics to track the GENERIC decomposition: - Effective Hamiltonian H_eff(θ) from antisymmetric flow - Diffusion operator D[ρ](θ) from symmetric flow - Entropy production rate - GENERIC structure preservation

Parameters:
__init__(exp_family, structure_constants=None, method='duhamel')[source]

Initialize GENERIC-aware dynamics.

Parameters:
  • exp_family (QuantumExponentialFamily) – The exponential family

  • structure_constants (np.ndarray, optional) – Lie algebra structure constants f_abc If None, will be computed from operators

  • method (str, optional) – Method for derivatives: ‘duhamel’ or ‘sld’

compute_generic_decomposition(theta)[source]

Compute full GENERIC decomposition at given θ.

Returns:

‘M’ : Jacobian matrix ‘S’ : Symmetric part ‘A’ : Antisymmetric part ‘H_eff’ : Effective Hamiltonian ‘eta’ : Hamiltonian coefficients ‘D_rho’ : Diffusion operator (if compute_diffusion=True) ‘entropy_production’ : dS/dt

Return type:

dict with keys

Parameters:

theta (ndarray)

integrate_reversible(theta_0, t_span, n_points=100)[source]

Integrate reversible (Hamiltonian) part only: -i[H_eff, ρ].

This integrates the antisymmetric flow in parameter space, which corresponds to unitary evolution in density matrix space.

Return type:

Dict[str, Any]

Parameters:
integrate_irreversible(theta_0, t_span, n_points=100)[source]

Integrate irreversible (dissipative) part only: D[ρ].

This integrates the symmetric flow in parameter space, which corresponds to entropy-increasing dissipation.

Return type:

Dict[str, Any]

Parameters:
integrate_with_monitoring(theta_0, t_span, n_points=100, compute_diffusion=False)[source]

Integrate full dynamics with GENERIC structure monitoring.

Parameters:
  • theta_0 (np.ndarray) – Initial parameters

  • t_span (Tuple[float, float]) – Time interval

  • n_points (int) – Number of evaluation points

  • compute_diffusion (bool) – Whether to compute D[ρ] at each step (expensive!)

Return type:

dict with trajectory and GENERIC monitoring data