The current QES architecture primarily focuses on pure states (
-
Thermal States: Systems in equilibrium at finite temperature
$T > 0$ , described by Gibbs ensembles$\rho \propto e^{-\beta H}$ . - Decoherence and Open Systems: Systems interacting with an environment, requiring Lindblad master equations or quantum channels.
- Reduced Density Matrices: Analyzing subsystems (entanglement entropy, partial traces) where the local state is mixed even if the global state is pure.
- Ensemble Averages: Statistical mixtures of pure states, often arising from classical uncertainty in preparation.
Introducing a DensityMatrix abstraction will allow QES to naturally handle these cases while leveraging the existing efficient operator stack.
The API is designed to be small, sharp, and consistent with existing QES patterns.
class DensityMatrix(State): # Assuming a State base class exists or will exist
"""
Represents a quantum density matrix.
"""
@classmethod
def from_pure(cls, psi: Union[np.ndarray, 'Array'], backend='default'):
"""Constructs rho = |psi><psi|."""
pass
@classmethod
def from_ensemble(cls, states: List[Union[np.ndarray, 'Array']], weights: List[float]):
"""Constructs rho = sum_i w_i |psi_i><psi_i|."""
pass
@classmethod
def from_matrix(cls, matrix: Union[np.ndarray, 'Array']):
"""Constructs rho from a dense or sparse matrix."""
pass
@classmethod
def thermal(cls, hamiltonian: 'Hamiltonian', beta: float, method='exact'):
"""
Constructs a thermal state exp(-beta H) / Z.
Method can be 'exact' (ED) or 'imaginary_time' (for MPO/NQS in future).
"""
pass def trace(self) -> float:
"""Returns Tr(rho). Should be close to 1.0."""
pass
def purity(self) -> float:
"""Returns Tr(rho^2). 1.0 for pure states, < 1.0 for mixed."""
pass
def entropy_vn(self) -> float:
"""Returns von Neumann entropy -Tr(rho log rho)."""
pass
def expectation(self, op: 'Operator') -> complex:
"""
Computes Tr(rho * op).
If rho is an ensemble {(p_i, psi_i)}, computes sum p_i <psi_i|op|psi_i>.
"""
pass
def partial_trace(self, subsystem: List[int]) -> 'DensityMatrix':
"""Returns the reduced density matrix for the specified subsystem."""
passFor closed systems starting in a mixed state:
$$ \rho(t) = U(t) \rho(0) U^\dagger(t) $$
where
def evolve(self, hamiltonian: 'Hamiltonian', t: float, method='krylov') -> 'DensityMatrix':
"""
Evolves the density matrix under the given Hamiltonian.
"""
passFor open systems or when vectorization is useful,
SpecialOperator and Hamiltonian are designed to act on vectors. To support density matrices without rewriting operators, we introduce the concept of Left and Right Actions:
-
Left Action (
$L_A$ ):$L_A \rho = A \rho$ . In vectorized form,$L_A \rightarrow A \otimes I$ . -
Right Action (
$R_A$ ):$R_A \rho = \rho A$ . In vectorized form,$R_A \rightarrow I \otimes A^T$ .
Since SpecialOperator implements matvec(psi), we can implement these actions on a DensityMatrix:
-
Dense Representation (
$D \times D$ matrix):-
$L_A$ : Applymatvecto each column of$\rho$ . -
$R_A$ : Applymatvec(of$A^\dagger$ ) to each row of$\rho$ (or column of$\rho^\dagger$ ) and take adjoint.
-
-
Ensemble Representation (
${p_i, |\psi_i\rangle}$ ):-
$L_A$ : Return new ensemble${p_i, A|\psi_i\rangle}$ . (Note: this makes the "ket" unnormalized, or requires re-normalization and weight update). - Expectation values are computed as averages over the ensemble.
-
This approach keeps the Operator API common: DensityMatrix consumes Operator methods, rather than requiring Operator to know about DensityMatrix.
-
Shapes:
- Dense:
(Nh, Nh) - Ensemble: List of
(Nh,)vectors.
- Dense:
-
Dtypes: Consistent with
Hamiltonian(float64/complex128). -
Hermiticity:
$\rho^\dagger = \rho$ . Operations should preserve this (within numerical tolerance). -
Trace:
$\text{Tr}(\rho) = 1$ . Evolution should preserve trace. -
Positivity:
$\rho \ge 0$ . Hard to enforce exactly in all truncations, but checks should be available.
-
Avoid Full Density Matrices: For large systems (
$N > 14$ ), full$D \times D$ matrices are infeasible.- Ensemble Method: Use Monte Carlo sampling of pure states (e.g., minimally entangled typical thermal states - METTS) or just a collection of pure states if the rank is low.
- Lazy Materialization: Only compute elements or contractions when needed.
-
Numba/JAX Compilation:
- The existing
SpecialOperatorinfrastructure uses Numba/JAX formatvec.DensityMatrixoperations should batch these calls. - For JAX, use
vmapto applymatvecacross the columns of a density matrix or the members of an ensemble. - Avoid recompiling kernels for every
rho; reuse the existingHamiltoniankernels.
- The existing
-
Low-Rank Approximations: Store
$\rho \approx V V^\dagger$ where$V$ is$D \times k$ ($k \ll D$ ). Evolution acts on$V$ .
-
Invariants:
- Trace = 1.
- Hermitian.
- Purity
$\le 1$ .
-
Consistency:
-
$\text{Tr}(\rho H)$ should match thermal energy. -
from_pure(psi).expectation(O)==psi.conj() @ O @ psi. - Evolution of
from_pure(psi)should match evolution ofpsi.
-