qml.math.choi_matrix¶
- choi_matrix(Ks, check_Ks=False)[source]¶
Compute the Choi matrix \(\Lambda\) of a quantum channel \(\mathcal{E}\),
\[\Lambda = (\mathbb{1} \otimes \mathcal{E})(|\phi^+ \rangle \langle \phi^+|) = \frac{1}{2^n} \sum_{ij=0}^{2^n-1} |i \rangle \langle j| \otimes \mathcal{E}(|i \rangle \langle j|),\]where \(|\phi^+ \rangle\) is the maximally entangled state \(|\phi^+\rangle = \frac{1}{\sqrt{2^n}} \sum_{i=0}^{2^n-1} |i\rangle \otimes |i\rangle\) between the qubit system the channel \(\mathcal{E}\) is acting on and additional “artificial” system of the same size.
We assume the channel \(\mathcal{E}(\rho) = \sum_\ell K_\ell^\dagger \rho K_\ell\) is provided in terms of its Kraus operators \(\{K_j\}\) (
Ks
) that are trace-preserving, hence \(\sum_j K_j^\dagger K_j = \mathbb{1}\).- Parameters:
Ks (TensorLike) – A list of Kraus operators with size
(2**n, 2**n)
that act onn
wires.check_Ks (bool) – Whether or not to check if the provided Kraus operators are trace-preserving, i.e. \(\sum_j K_j^\dagger K_j = \mathbb{1}\). Default is
False
.
- Returns:
The Choi matrix \(\Lambda\) of size
(2**(2n), 2**(2n))
- Return type:
TensorLike
Examples
The simplest quantum channel is a single unitary gate. In that case, the Kraus operators reduce to the unitary gate itself.
>>> import pennylane as qml >>> Ks = [qml.matrix(qml.CNOT((0, 1)))] >>> Lambda = qml.math.choi_matrix(Ks) >>> Lambda.shape (16, 16)
The resulting Choi matrix is a density matrix, so its trace sums to 1. Because the channel is unitary, the resulting Choi state is pure, which can be seen from \(\text{tr}\left( \Lambda^2 \right) = 1\)
>>> np.trace(Lambda), np.trace(Lambda @ Lambda) (np.float64(1.0), np.float64(1.0))
We can construct a non-unitary channel by taking different unitary operators and weighting them such that the trace is preserved (i.e., the squares of the coefficients sum to one).
>>> Ks = [np.sqrt(0.3) * qml.CNOT((0, 1)), np.sqrt(1-0.3) * qml.X(0)] >>> Ks = [qml.matrix(op, wire_order=range(2)) for op in Ks] >>> Lambda = qml.math.choi_matrix(Ks)
In this case, the resulting Choi matrix does not correspond to a pure state, as seen by \(\text{tr}\left( \Lambda^2 \right) < 1\).
>>> np.trace(Lambda), np.trace(Lambda @ Lambda) (np.float64(1.0), np.float64(0.58))