qig.core

Core quantum information utilities for density matrices and entropy calculations.

This module provides the fundamental building blocks used throughout the library:

  • Partial tracepartial_trace(): reduce a bipartite density matrix to one subsystem.

  • Von Neumann entropyvon_neumann_entropy(): compute \(S(\rho) = -\operatorname{tr}(\rho \log \rho)\).

  • Marginal entropiesmarginal_entropies(): joint and subsystem entropies for bipartite systems.

  • LME statecreate_lme_state(): construct a Lindblad-Master-Equation (maximally mixed) state with specified marginals.

  • GENERIC decompositiongeneric_decomposition(): split a flow matrix \(M\) into symmetric (dissipative) and antisymmetric (reversible) parts.

  • Loewner kernelloewner_kernel(): compute the Kubo-Mori / BKM divided-difference kernel matrix in the eigenbasis of a density matrix. This is the central object linking exponential-family geometry to the BKM Fisher information metric.

    \[\begin{split}C_{ij} = \begin{cases} \dfrac{\lambda_i - \lambda_j}{\log \lambda_i - \log \lambda_j} & \lambda_i \neq \lambda_j \\[6pt] \lambda_i & \lambda_i = \lambda_j \end{cases}\end{split}\]

    In the LME limit all \(\lambda_i \to 1/D\) and every entry \(C_{ij} \to 1/D\), recovering flat Fisher geometry.

Core utilities for the quantum inaccessible game.

This module contains the basic state-manipulation and entropy helpers used throughout the quantum inaccessible game code:

  • partial traces

  • von Neumann entropy

  • construction of locally maximally entangled (LME) states

  • marginal entropies

qig.core.partial_trace(rho, dims, keep)[source]

Compute partial trace over all subsystems except ‘keep’.

Parameters:
  • rho (array, shape (D, D)) – Density matrix for composite system

  • dims (list of int) – Dimensions of each subsystem [d1, d2, …]

  • keep (int) – Index of subsystem to keep (0-indexed)

Returns:

rho_reduced – Reduced density matrix

Return type:

array, shape (d_keep, d_keep)

qig.core.von_neumann_entropy(rho, regularisation=1e-14)[source]

Compute von Neumann entropy S(rho) = -Tr(rho log rho).

Parameters:
  • rho (array, shape (d, d)) – Density matrix

  • regularisation (float) – Small value added to eigenvalues to avoid log(0)

Returns:

entropy – Von Neumann entropy

Return type:

float

qig.core.create_lme_state(n_sites, d)[source]

Create a locally maximally entangled (LME) state.

For even n_sites, creates n_sites/2 maximally entangled pairs. For odd n_sites, leaves one site pure.

Parameters:
  • n_sites (int) – Number of sites/subsystems

  • d (int) – Local dimension at each site

Return type:

Tuple[ndarray, list]

Returns:

  • rho (array, shape (d**n_sites, d**n_sites)) – LME state density matrix

  • dims (list of int) – Dimensions [d, d, …, d]

qig.core.marginal_entropies(rho, dims)[source]

Compute marginal entropies for all subsystems.

Parameters:
  • rho (array, shape (D, D)) – Joint density matrix

  • dims (list of int) – Dimensions of subsystems

Returns:

h – Marginal entropies [h_1, h_2, …]

Return type:

array, shape (n_sites,)

qig.core.generic_decomposition(M)[source]

Decompose Jacobian into symmetric and antisymmetric parts.

M = S + A where S = (M + M^T)/2, A = (M - M^T)/2

Parameters:

M (array, shape (n, n)) – Jacobian matrix

Return type:

Tuple[ndarray, ndarray]

Returns:

  • S (array, shape (n, n)) – Symmetric part (dissipative)

  • A (array, shape (n, n)) – Antisymmetric part (conservative)

qig.core.loewner_kernel(rho0, tol=1e-12)[source]

Compute the Loewner (Kubo-Mori / BKM) divided-difference kernel for rho0.

The kernel is defined entry-wise in the eigenbasis of rho0 as:

c(lambda_i, lambda_j) = (lambda_i - lambda_j) / (log lambda_i - log lambda_j)
                                                      for lambda_i != lambda_j
c(lambda_i, lambda_i) = lambda_i                      (L'Hopital limit)

For a perturbation delta_K in the eigenbasis of rho0, the corresponding first-order perturbation of rho is:

delta_rho_{ij} = c(lambda_i, lambda_j) * delta_K_{ij}

This is the Frechet derivative of exp(-K - psi(K)) pushed forward from modular-generator coordinates to density-matrix coordinates.

In the LME limit (all lambda_i -> 1/d), c(lambda_i, lambda_j) -> 1/d for all i, j, and the induced Fisher metric degenerates to d * Id (flat geometry).

Parameters:
  • rho0 (array, shape (D, D)) – Background density matrix (Hermitian, positive definite)

  • tol (float) – Threshold below which eigenvalue differences are treated as degenerate

Return type:

Tuple[ndarray, ndarray, ndarray]

Returns:

  • C (array, shape (D, D)) – Kernel matrix in the eigenbasis of rho0. C[i, j] = c(lambda_i, lambda_j).

  • vals (array, shape (D,)) – Eigenvalues of rho0 (sorted ascending, clipped to >= 1e-14)

  • vecs (array, shape (D, D)) – Eigenvectors of rho0 as columns (unitary matrix)

Notes

To obtain the Loewner map as an operator on the full space of D x D matrices, use the returned vecs to rotate: for any matrix X in the original basis, X_eig = vecs.conj().T @ X @ vecs, then (J_rho0(X))_eig[i,j] = C[i,j]*X_eig[i,j], then rotate back: J_rho0(X) = vecs @ (C * X_eig) @ vecs.conj().T.