Quick Start

This quick start guide demonstrates the basic usage of qig for quantum information geometry.

Creating a Quantum Exponential Family

The core object is QuantumExponentialFamily, which represents a quantum state as \(\rho(\theta) = \exp(\sum_a \theta_a F_a - \psi(\theta))\).

from qig.exponential_family import QuantumExponentialFamily
import numpy as np

# Create a qutrit (d=3) exponential family with Gell-Mann operators
exp_fam = QuantumExponentialFamily(d=3, basis_type='gell-mann')

# Natural parameters (8 for a qutrit with traceless operators)
theta = np.zeros(exp_fam.n_params)

# Get the density matrix
rho = exp_fam.rho_from_theta(theta)
print(f"Density matrix shape: {rho.shape}")

Computing the Fisher Information Metric

The Fisher information metric (BKM metric) is computed using the Kubo-Mori formula:

# Compute the Fisher information matrix G(θ)
G = exp_fam.fisher_information(theta)

print(f"Fisher metric shape: {G.shape}")
print(f"Metric is symmetric: {np.allclose(G, G.T)}")

Constrained Dynamics

Study dynamics constrained to preserve marginal entropies:

from qig.dynamics import InaccessibleGameDynamics

# Create dynamics object
dynamics = InaccessibleGameDynamics(exp_fam)

# An initial state (close to thermal maximum, i.e. small perturbation from origin)
theta_0 = np.random.randn(exp_fam.n_params) * 0.1

# Solve constrained maximum entropy dynamics
result = dynamics.solve_constrained_maxent(
    theta_init=theta_0,
    n_steps=1000,
    dt=0.001,
    convergence_tol=1e-6
)

print(f"Converged: {result['converged']}")
print(f"Final entropy: {result['entropy'][-1]:.6f}")
print(f"Constraint preserved: {np.abs(result['C_values'][-1] - result['C_values'][0]) < 1e-6}")

Working with Entanglement

For studying entanglement, use the pair operator basis:

# Create exponential family with pair operators
exp_fam_pairs = QuantumExponentialFamily(
    d=3,
    basis_type='gell-mann',
    include_pairs=True
)

print(f"With pairs: {exp_fam_pairs.n_params} parameters")

# Compute mutual information
theta = np.random.randn(exp_fam_pairs.n_params) * 0.1
rho = exp_fam_pairs.rho_from_theta(theta)

# Get marginal entropies
from qig.core import marginal_entropies
h = marginal_entropies(rho, dims=[3, 3])
mutual_info = h[0] + h[1] - (-np.trace(rho @ np.log(rho)))

print(f"Mutual information: {mutual_info:.6f} nats")

Next Steps