Tensor Products and Partial Trace (With Intuition)
February 4, 2025
To describe multipartite quantum systems (two qubits, a qubit + an oscillator, etc.), we expand the Hilbert space using the tensor product. The tensor product is the standard way to combine:
- state vectors into joint state vectors
- operators into joint operators
Later, when we only care about a part of a larger system, we use the partial trace to obtain a subsystem’s reduced density matrix.
Tensor products: building bigger state spaces
If one qubit lives in a 2D space and another qubit lives in a 2D space, then together they live in a dimensional space:
Example: two-qubit basis states
The computational basis states combine as:
Operators on a composite system
If acts on qubit and acts on qubit , then the joint operator is:
To apply an operator to only one subsystem, you tensor it with identity on the other subsystem(s). For example, “apply to the first qubit and do nothing to the second” is:
Density matrices (why we need them)
Statevectors describe pure states. But when you look at a subsystem of a larger state—especially an entangled one—the subsystem is often mixed. Mixed states are represented by density matrices .
For a pure state , the density matrix is:
Partial trace: extracting a subsystem
Given a joint density matrix , the reduced state of subsystem is:
Intuitively, you are “averaging over” (tracing out) the degrees of freedom of subsystem .
Example: Bell state → maximally mixed single-qubit state
Consider:
If you trace out qubit , you get:
That means: looking at qubit alone, the outcome of measuring in the computational basis is 50/50, even though the pair is perfectly correlated.
Python example (Qiskit): partial trace of a Bell state
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector, partial_trace, DensityMatrix
# Build a Bell state |Phi+> = (|00> + |11>)/sqrt(2)
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
psi = Statevector.from_instruction(qc)
rho_ab = DensityMatrix(psi)
# Trace out qubit 1 (keep qubit 0)
rho_a = partial_trace(rho_ab, [1])
print(rho_a)You should see a 2×2 matrix close to .
When do you need partial traces in quantum computing?
- Entanglement reasoning: what does each qubit look like individually?
- Noise models: open-system dynamics naturally produce mixed states
- Error correction: logical information is encoded nonlocally; local views can look random
Next
- If you have not read it yet: Dirac notation
- For a geometric picture of single-qubit mixed states: Bloch sphere