A state vector carries a global phase that no measurement can see: [1j, 0] and [1, 0] are the same state. The density matrix is a way of writing a state without that leftover phase. For a state |\psi\rangle with amplitudes \psi_0, \dots, \psi_{d-1} it is the d \times d matrix
where \overline{\psi_j} is the complex conjugate of amplitude j (in Python, complex(x).conjugate()). Row i is the amplitude \psi_i times the conjugated state. Multiplying |\psi\rangle by e^{i\phi} multiplies \psi_i by e^{i\phi} and \overline{\psi_j} by e^{-i\phi}, so \rho does not change.
Write density(state) that returns \rho as a list of rows (rho[i][j]), for a normalised state of 1 to 3 qubits. The diagonal \rho_{ii} = |\psi_i|^2 holds the measurement probabilities, so the trace (the sum of the diagonal) is 1, and \rho_{ji} = \overline{\rho_{ij}} (the matrix is Hermitian): two quick checks for your own answer.
Examples
Input: state = [0.6, 0.8j]
Output: [[0.36, -0.48j], [0.48j, 0.64]]
Explanation: rho[0][1] = 0.6 * conj(0.8j) = 0.6 * (-0.8j) = -0.48j.
Input: state = [0, 1j]
Output: [[0, 0], [0, 1]]
Explanation: 1j * conj(1j) = 1j * (-1j) = 1: the phase 1j is gone.
Input: state = [0.7071067811865476, 0, 0, 0.7071067811865476]
Output: [[0.5, 0, 0, 0.5], [0, 0, 0, 0], [0, 0, 0, 0], [0.5, 0, 0, 0.5]]
Entries may be ints, floats or complex numbers; each is compared with a tolerance of 1e-6.
Goals
- Build the density matrix $|\psi\rangle\langle\psi|$ of a state as an outer product
- Put the complex conjugate on the column index, not the row index
- See that a global phase disappears from the density matrix