Module: qig.symbolic

The symbolic computation subpackage for exact GENERIC decomposition.

Overview

The qig.symbolic package provides exact symbolic computation for qutrit pair systems at the LME (Locally Maximally Entangled) origin. Key features:

  • Exact exp(K) via block decomposition (no Taylor approximation)

  • Block structure: 9×9 → 3×3 + 2×2 + 1×1×4

  • Numeric-symbolic bridge for connecting exponential family θ to block params

Submodules

qig.symbolic.lme_exact

Core module for exact LME computations.

EXACT symbolic computation for LME qutrit pairs.

Key insight: For maximally entangled states, the 9×9 eigenvalue problem decomposes into blocks with at most QUADRATIC eigenvalues:

9×9 → 3×3 + 2×2 + 1×1 + 1×1 + 1×1 + 1×1

This enables EXACT exp(K) computation with NO Taylor approximation.

The 20 block-preserving generators span the full entangled subspace, allowing exploration of ALL maximally entangled states.

Numeric correspondence

In the numeric codebase, the same 9×9 Hilbert space and su(9) generators appear via:

  • qig.pair_operators.pair_basis_generators(d=3), and

  • qig.exponential_family.QuantumExponentialFamily(n_pairs=1, d=3, pair_basis=True), whose operators attribute is a concrete su(9) basis.

The helper numeric_lme_blocks_from_theta defined near the end of this file bridges these two views: given a numeric θ and operator list (as used by the exponential family), it reconstructs the block-decomposed K in the same permutation/basis used here symbolically. This allows direct comparison between:

  • the symbolic block parameters (e.g. the 2×2 block entries that feed into quadratic eigenvalues), and

  • the numeric Bell/LME parameters θ obtained from QuantumExponentialFamily.get_bell_state_parameters.

qig.symbolic.lme_exact.gell_mann_symbolic()[source]

8 Gell-Mann matrices (3×3) with Tr(λ_a λ_b) = 2δ_ab.

Return type:

List[MutableDenseMatrix]

qig.symbolic.lme_exact.permutation_matrix()[source]

Permutation to block basis: {|00⟩,|11⟩,|22⟩} + rest.

Original: |00⟩,|01⟩,|02⟩,|10⟩,|11⟩,|12⟩,|20⟩,|21⟩,|22⟩

Reordered: |00⟩,|11⟩,|22⟩,|01⟩,|02⟩,|10⟩,|12⟩,|20⟩,|21⟩

Return type:

MutableDenseMatrix

qig.symbolic.lme_exact.block_preserving_generators()[source]

20 generators that preserve the {|00⟩,|11⟩,|22⟩} block structure.

Return type:

Tuple[List[MutableDenseMatrix], List[str]]

Returns:

  • generators (list of 9×9 matrices)

  • names (list of string labels)

qig.symbolic.lme_exact.extract_blocks(K_block)[source]

Extract sub-blocks from K in block basis.

K decomposes as: - 3×3 entangled block (indices 0-2) - 2×2 block (indices 3,5 coupled) - 4 isolated 1×1 blocks

Return type:

Dict[str, MutableDenseMatrix]

Parameters:

K_block (MutableDenseMatrix)

qig.symbolic.lme_exact.eigenvalues_2x2(M)[source]

Exact eigenvalues of 2×2 Hermitian matrix using quadratic formula.

For M = [[a, b], [b*, c]]: λ = (a+c)/2 ± sqrt((a-c)²/4 + |b|²)

Return type:

Tuple

Parameters:

M (MutableDenseMatrix)

qig.symbolic.lme_exact.eigenvalues_3x3_block(M)[source]

Eigenvalues of 3×3 matrix with potential 2×2 + 1×1 block structure.

If M has form [[2×2 block, 0], [0, isolated]], eigenvalues are quadratic from 2×2 block + isolated element.

Return type:

Tuple

Parameters:

M (MutableDenseMatrix)

qig.symbolic.lme_exact.exact_exp_K_lme(theta)[source]

EXACT exp(K) for LME-preserving dynamics.

Parameters:

theta (dict) – Dictionary mapping generator names to symbolic coefficients. Keys should match names from block_preserving_generators().

Returns:

9×9 matrix exp(K), computed exactly via block decomposition.

Return type:

Matrix

qig.symbolic.lme_exact.exact_rho_lme(theta)[source]

EXACT density matrix ρ = exp(K) / Tr(exp(K)).

Return type:

MutableDenseMatrix

Parameters:

theta (Dict[str, Symbol])

qig.symbolic.lme_exact.numeric_lme_blocks_from_theta(theta, operators)[source]

Map numeric exponential-family parameters to the LME block structure.

This provides a bridge between:

  • the numeric representation used by QuantumExponentialFamily(n_pairs=1, d=3, pair_basis=True) (θ plus a concrete su(9) operator basis), and

  • the symbolic block decomposition used in this module (3×3 entangled block + 2×2 block + 1×1 diagonals).

Parameters:
  • theta (np.ndarray, shape (n_params,)) – Natural parameters in the same ordering as operators. For the LME qutrit pair this should be the 80-dimensional θ used by the pair-based exponential family.

  • operators (list of np.ndarray) – List of traceless Hermitian generators (e.g., the exp_fam.operators attribute of a QuantumExponentialFamily(n_pairs=1, d=3, pair_basis=True)).

Returns:

blocks – Dictionary with numeric blocks in the same layout as extract_blocks():

  • 'ent_3x3' : 3×3 entangled block

  • 'block_2x2' : 2×2 block (indices 3,5 in block basis)

  • 'diag_1', 'diag_2', 'diag_3', 'diag_4' : 1×1 entries

Return type:

dict

qig.symbolic.lme_exact.symbolic_partial_trace(rho, trace_out)[source]

Symbolic partial trace for 3⊗3 system.

Parameters:
  • rho (9×9 Matrix)

  • trace_out (1 or 2 (which subsystem to trace out))

Return type:

3×3 Matrix

qig.symbolic.lme_exact.exact_rho1_lme(theta)[source]

EXACT reduced density matrix ρ₁ = Tr₂(ρ).

Return type:

MutableDenseMatrix

Parameters:

theta (Dict[str, Symbol])

qig.symbolic.lme_exact.exact_rho2_lme(theta)[source]

EXACT reduced density matrix ρ₂ = Tr₁(ρ).

Return type:

MutableDenseMatrix

Parameters:

theta (Dict[str, Symbol])

qig.symbolic.lme_exact.exact_marginal_entropy_lme(rho_marginal)[source]

EXACT von Neumann entropy of 3×3 marginal density matrix.

Uses block structure: eigenvalues are quadratic. h = -Σᵢ λᵢ log(λᵢ)

Return type:

Expr

Parameters:

rho_marginal (MutableDenseMatrix)

qig.symbolic.lme_exact.exact_constraint_lme(theta)[source]

EXACT constraint C = h₁ + h₂.

Return type:

Expr

Parameters:

theta (Dict[str, Symbol])

qig.symbolic.lme_exact.create_theta_symbols()[source]

Create symbolic parameters for the 20 block-preserving generators.

Return type:

Tuple[Dict[str, Symbol], List[Symbol]]

Returns:

  • theta_dict (dict mapping generator names to symbols)

  • theta_list (ordered list of symbols (for differentiation))

qig.symbolic.lme_exact.exact_psi_lme(theta)[source]

EXACT cumulant generating function ψ = log Tr(exp(K)).

Return type:

Expr

Parameters:

theta (Dict[str, Symbol])

qig.symbolic.lme_exact.exact_constraint_gradient_lme(theta, theta_list)[source]

EXACT constraint gradient a = ∇C = ∇(h₁ + h₂).

Parameters:
  • theta (dict mapping generator names to symbols)

  • theta_list (ordered list of symbols for differentiation)

Returns:

Matrix

Return type:

20×1 column vector

qig.symbolic.lme_exact.exact_fisher_information_lme(theta, theta_list)[source]

EXACT Fisher information G = ∇²ψ (BKM metric).

Parameters:
  • theta (dict mapping generator names to symbols)

  • theta_list (ordered list of symbols for differentiation)

Returns:

Matrix

Return type:

20×20 symmetric matrix

qig.symbolic.lme_exact.exact_lagrange_multiplier_lme(a, G, theta_list, do_simplify=False)[source]

EXACT Lagrange multiplier ν = (aᵀGθ)/(aᵀa).

Parameters:
  • a (20×1 constraint gradient)

  • G (20×20 Fisher information)

  • theta_list (list of symbols)

  • do_simplify (bool) – Whether to simplify (SLOW)

Return type:

Scalar expression for ν

qig.symbolic.lme_exact.exact_grad_lagrange_multiplier_lme(a, G, nu, theta_list, do_simplify=False)[source]

EXACT gradient of Lagrange multiplier ∇ν.

Parameters:
  • a (20×1 constraint gradient)

  • G (20×20 Fisher information)

  • nu (scalar Lagrange multiplier)

  • theta_list (list of symbols)

  • do_simplify (bool) – Whether to simplify each derivative (SLOW for complex expressions)

Returns:

Matrix

Return type:

20×1 column vector

qig.symbolic.lme_exact.exact_antisymmetric_part_lme(a, grad_nu)[source]

EXACT antisymmetric part A = (1/2)[a(∇ν)ᵀ - (∇ν)aᵀ].

Parameters:
  • a (20×1 constraint gradient)

  • grad_nu (20×1 gradient of Lagrange multiplier)

Returns:

Matrix

Return type:

20×20 antisymmetric matrix

qig.symbolic.lme_exact.exact_constraint_hessian_lme(theta, theta_list, do_simplify=False)[source]

EXACT constraint Hessian ∇²C.

Returns n×n matrix of second derivatives of C = h₁ + h₂.

Return type:

MutableDenseMatrix

Parameters:
qig.symbolic.lme_exact.exact_nabla_G_theta_lme(G, theta_list)[source]

EXACT (∇G)[θ] = Σ_k (∂G_ij/∂θ_k) θ_k.

Third derivatives of ψ contracted with θ.

Return type:

MutableDenseMatrix

Parameters:
  • G (MutableDenseMatrix)

  • theta_list (List[Symbol])

qig.symbolic.lme_exact.exact_jacobian_lme(theta, theta_list)[source]

EXACT full Jacobian M = -G - (∇G)[θ] + ν∇²C + a(∇ν)ᵀ.

Return type:

MutableDenseMatrix

Parameters:
qig.symbolic.lme_exact.exact_symmetric_part_lme(M)[source]

EXACT symmetric part S = (M + Mᵀ)/2.

Return type:

MutableDenseMatrix

Parameters:

M (MutableDenseMatrix)

qig.symbolic.lme_exact.compute_full_chain_lme(theta_dict=None, theta_list=None, simplify_intermediate=True)[source]

Compute the full chain: exp(K) → ρ → h → a → G → ν → ∇ν → M → S, A.

Returns dict with all intermediate results.

Return type:

Dict

Parameters:
  • theta_dict (Dict[str, Symbol])

  • theta_list (List[Symbol])

  • simplify_intermediate (bool)

qig.symbolic.lme_exact.test_exact_lme()[source]

Test exact LME computation.

Example Usage

Basic symbolic computation:

from qig.symbolic.lme_exact import (
    exact_exp_K_lme,
    exact_constraint_lme,
    block_preserving_generators,
)
import sympy as sp

# Create symbolic parameters
a = sp.Symbol('a', real=True)
c = sp.Symbol('c', real=True)
theta = {'λ3⊗I': a, 'λ1⊗λ1': c}

# Exact computations
exp_K = exact_exp_K_lme(theta)
C = exact_constraint_lme(theta)

Bridging numeric and symbolic:

from qig.symbolic.lme_exact import numeric_lme_blocks_from_theta
from qig.exponential_family import QuantumExponentialFamily

# Numeric θ from exponential family
qef = QuantumExponentialFamily(n_pairs=1, d=3, pair_basis=True)
theta = qef.get_bell_state_parameters(log_epsilon=-20)

# Extract symbolic-style blocks
blocks = numeric_lme_blocks_from_theta(theta, qef.operators)
print(blocks['ent_3x3'])  # 3×3 entangled block

See Also