qig.pair_operators

Bell states, Gell-Mann generators, and two-qubit operators.

Operator bases for entangled pairs in Matrix Exponential Families.

This module provides generators for su(d²) Lie algebras, which act on the Hilbert space of a pair of d-level systems (e.g., two qubits for d=2). These operators can generate entangled states, unlike local operators.

qig.pair_operators.gell_mann_generators(d)[source]

Generate the d²-1 Gell-Mann matrices for su(d).

These are traceless Hermitian matrices that generalize the Pauli matrices. For d=2, this gives the three Pauli matrices. For d=3, this gives the eight Gell-Mann matrices.

The construction follows the standard pattern:

  • Symmetric matrices: |j⟩⟨k| + |k⟩⟨j| for j < k

  • Antisymmetric matrices: -i(|j⟩⟨k| - |k⟩⟨j|) for j < k

  • Diagonal matrices: sum_{l=0}^{j-1} |l⟩⟨l| - j|j⟩⟨j| for j = 1,…,d-1

Parameters:

d (int) – Dimension of the Hilbert space

Returns:

List of d²-1 traceless Hermitian matrices of size d×d

Return type:

List[np.ndarray]

Notes

The matrices are normalized to have Tr(λ_a λ_b) = 2δ_{ab}.

qig.pair_operators.pair_basis_generators(d)[source]

Generate su(d²) generators for a pair of d-level systems.

These act on the d²-dimensional Hilbert space of a pair (e.g., two qubits give d=2, d²=4, with 15 generators in su(4)).

Parameters:

d (int) – Dimension of each individual system (e.g., 2 for qubits, 3 for qutrits)

Returns:

List of d⁴-1 traceless Hermitian matrices of size d²×d²

Return type:

List[np.ndarray]

Examples

>>> # For a qubit pair
>>> generators = pair_basis_generators(d=2)
>>> len(generators)
15
>>> generators[0].shape
(4, 4)
qig.pair_operators.bell_state(d, k=0)[source]

Create a maximally entangled state for a pair of d-level systems.

Returns the state vector |Φₖ⟩ = (1/√d) ∑_{j=0}^{d-1} |j, (j+k) mod d⟩.

For k=0, this is the standard Bell state (1/√d) ∑_j |jj⟩.

Parameters:
  • d (int) – Dimension of each subsystem

  • k (int, default 0) – Bell state index (0 to d-1). Different k give orthogonal states. k=0: |00⟩ + |11⟩ + ... (standard) k=1: |01⟩ + |12⟩ + |20⟩ + ... (cyclic shift)

Returns:

State vector of length d², normalized

Return type:

np.ndarray

Notes

All d Bell states are maximally entangled with the same properties: - Global purity: S(ρ) = 0 - Marginals: ρ_A = ρ_B = I/d - Entanglement: maximal for dimension d

The states are mutually orthogonal: ⟨Φₖ|Φₗ⟩ = δₖₗ

Examples

>>> psi = bell_state(d=2, k=0)  # |00⟩ + |11⟩
>>> psi
array([0.70710678+0.j, 0.        +0.j, 0.        +0.j, 0.70710678+0.j])
>>> psi = bell_state(d=2, k=1)  # |01⟩ + |10⟩
>>> psi
array([0.        +0.j, 0.70710678+0.j, 0.70710678+0.j, 0.        +0.j])
qig.pair_operators.bell_state_density_matrix(d)[source]

Create the density matrix of a maximally entangled pair state.

Returns ρ = |Φ⟩⟨Φ| where |Φ⟩ = (1/√d) ∑_j |jj⟩.

This is a pure state (Tr(ρ²) = 1) that is globally pure but locally maximally mixed: both marginals have entropy log(d).

Parameters:

d (int) – Dimension of each subsystem

Returns:

Density matrix of size d²×d², positive semidefinite with trace 1

Return type:

np.ndarray

Notes

Properties of the Bell state: - Global purity: S(ρ) = 0 - Local marginals: ρ_A = ρ_B = I/d (maximally mixed) - Marginal entropies: S(ρ_A) = S(ρ_B) = log(d) - Mutual information: I = 2log(d) (maximal)

qig.pair_operators.multi_pair_basis(n_pairs, d)[source]

Generate direct sum operator basis for n independent pairs.

Creates operators of the form F_α^(k) = I ⊗ … ⊗ F_α ⊗ … ⊗ I, where F_α is at position k.

Parameters:
  • n_pairs (int) – Number of independent pairs

  • d (int) – Dimension of each subsystem (e.g., 2 for qubits)

Return type:

Tuple[List[ndarray], List[int]]

Returns:

  • operators (List[np.ndarray]) – List of n(d⁴-1) operators, each of size (d²)ⁿ × (d²)ⁿ

  • pair_indices (List[int]) – Index of which pair each operator acts on

Notes

The resulting Fisher metric will be block-diagonal, with one block per pair. Cross-pair elements vanish: G_{(k,i),(k’,j)} = 0 for k≠k’.

Examples

>>> # Two qubit pairs
>>> ops, indices = multi_pair_basis(n_pairs=2, d=2)
>>> len(ops)
30
>>> ops[0].shape
(16, 16)
>>> indices[:15]  # First 15 operators act on pair 0
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> indices[15:] # Next 15 operators act on pair 1
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
qig.pair_operators.product_of_bell_states(n_pairs, d, bell_indices=None)[source]

Create a product state of n maximally entangled pairs.

Returns |Ψ⟩ = |Φₖ₁⟩⊗|Φₖ₂⟩⊗...⊗|Φₖₙ⟩ where each |Φₖ⟩ is a Bell state.

Parameters:
  • n_pairs (int) – Number of pairs

  • d (int) – Dimension of each subsystem

  • bell_indices (list of int, optional) – Which Bell state (k=0,…,d-1) to use for each pair. If None, uses k=0 (standard Bell state) for all pairs.

Returns:

State vector of length (d²)ⁿ

Return type:

np.ndarray

Notes

This is the “origin” of the inaccessible game. Properties: - Globally pure: S(ρ) = 0 - All 2n marginals maximally mixed: S(ρ_i) = log(d) for all i - Pairs are entangled, but no cross-pair entanglement - Total marginal entropy: C = 2n·log(d)

Different bell_indices give orthogonal product states that share the same constraint value C and marginal entropies, but represent different “origins” in the exponential family.

Examples

>>> # Standard: |Φ₀⟩⊗|Φ₀⟩ = (|00⟩+|11⟩)⊗(|00⟩+|11⟩)
>>> psi = product_of_bell_states(n_pairs=2, d=2)
>>> # Mixed: |Φ₀⟩⊗|Φ₁⟩ = (|00⟩+|11⟩)⊗(|01⟩+|10⟩)
>>> psi = product_of_bell_states(n_pairs=2, d=2, bell_indices=[0, 1])
qig.pair_operators.generalised_bell_basis(d)[source]

Construct the full generalised Bell basis for a pair of d-level systems.

The generalised Bell states are defined as

\[|\Phi_{mn}\rangle = \frac{1}{\sqrt{d}} \sum_{k=0}^{d-1} \omega^{km}\, |k\rangle \otimes |(k+n)\bmod d\rangle, \quad \omega = e^{2\pi i/d}.\]
Parameters:

d (int) – Dimension of each subsystem (so the pair lives in \(\mathbb{C}^{d^2}\)).

Returns:

U – Unitary matrix whose column m * d + n is |Φ_{mn}⟩. Satisfies U.conj().T @ U = I (verified internally).

Return type:

np.ndarray, shape (d², d²)

Notes

The existing bell_state() covers only the m=0 sub-family (cyclic-shift Bell states). This function returns all d² orthonormal Bell states, spanning a complete basis for the pair Hilbert space.

Every column |Φ_{mn}⟩ has exactly maximally mixed marginals: Tr_B(|Φ_{mn}⟩⟨Φ_{mn}|) = I/d.

Examples

>>> U = generalised_bell_basis(d=2)
>>> U.shape
(4, 4)
>>> import numpy as np
>>> np.allclose(U.conj().T @ U, np.eye(4))
True
qig.pair_operators.near_bell_hamiltonian(d, delta=0.1)[source]

Hermitian Hamiltonian diagonal in the generalised Bell basis, suitable for near-Bell Gibbs-state experiments.

The spectrum is:

  • |Φ_{00}⟩ eigenvalue 0 (ground state, reference Bell state)

  • |Φ_{01}⟩ eigenvalue delta (one neighbouring level)

  • all others eigenvalue 1

Because every Bell state has exactly maximally mixed marginals (ρ_A = I/d), the Gibbs state ρ(β) = exp(-βH)/Z satisfies:

  • Exact LME at every temperature (marginals = I/d for all β).

  • Approaches pure Bell state as β → ∞.

  • Gibbs-locked: K_0 = βH commutes with H trivially.

Parameters:
  • d (int) – Dimension of each subsystem.

  • delta (float, default 0.1) – Energy gap of the neighbouring Bell level above the ground state.

Returns:

H – Hermitian matrix with the spectrum described above.

Return type:

np.ndarray, shape (d², d²)

Examples

>>> H = near_bell_hamiltonian(d=2, delta=0.1)
>>> H.shape
(4, 4)
>>> import numpy as np
>>> np.allclose(H, H.conj().T)
True
qig.pair_operators.near_bell_gibbs_frame(d, delta=0.1, beta=5.0)[source]

Convenience constructor for the canonical near-Bell testbed.

Builds a GibbsLockedFrame from the near-Bell Hamiltonian returned by near_bell_hamiltonian().

The resulting frame has:

  • Gibbs state exactly LME (marginals = I/d) for every beta.

  • Gibbs-lock residual ||[K_0, H]||_F < 1e-12 (trivially satisfied since K_0 = β H).

  • Pure-Bell limit as beta .

Parameters:
  • d (int) – Dimension of each subsystem.

  • delta (float, default 0.1) – Energy gap passed to near_bell_hamiltonian().

  • beta (float, default 5.0) – Inverse temperature for the Gibbs state.

Returns:

frame – Fully initialised frame centred near the Bell-state boundary.

Return type:

GibbsLockedFrame

Examples

>>> frame = near_bell_gibbs_frame(d=2, delta=0.1, beta=5.0)
>>> frame.gibbs_lock_residual() < 1e-10
True