Describing quantum noise: Quantum channels¶
In this notebook, we demonstrate how to describe noise in the Quantum Learning Machine.
Definitions¶
Quantum noise is generally described mathematically by completely positive, trace-preserving maps or quantum channels, which we will denote $\mathcal{E}(\rho)$ in the following (with $\rho$ the density matrix).
A quantum channel $\mathcal{E}$ can be represented by its Kraus operators $\lbrace E_k \rbrace_{k=1\dots K}$. In this Kraus or operator-sum representation, $\mathcal{E}$ acts on a given density matrix $\rho$ as follows:
$$\mathcal{E}(\rho) = \sum_{k=1}^K E_k \rho E_k^\dagger $$
$K$ is called the Kraus rank of the quantum channel. Since a quantum channel is trace preserving, the Kraus operators fulfill the relation
$$\sum_k E_k^\dagger E_k = \mathbf{1} $$
Implementation in the Quantum Learning Machine¶
In the QLM, quantum channels and related tools are implemented in the qat.quops
(for "quantum operations") module. The Kraus representation of a quantum channel is implemented by the QuantumChannelKraus
object.
Construction¶
In the code snippet below, we create a quantum channel with two Kraus operators $$E_0 = \sqrt{p} \mathbf{1},\;\;E_1 = \sqrt{1-p} \mathbf{X}$$ where $\mathbf{X}$ is the Pauli X matrix, and $p=0.75$.
import numpy as np
from qat.quops import QuantumChannelKraus
Pauli_X = np.array([[0.,1.],[1.,0.]])
my_channel = QuantumChannelKraus(kraus_operators=[np.sqrt(0.75)*np.identity(2), np.sqrt(0.25)*Pauli_X],
name="my simple channel")
# let us print the Kraus operators and the Kraus rank
print("Kraus operators = ", my_channel.kraus_operators)
print("Kraus rank =", my_channel.kraus_rank())
Kraus operators = [array([[0.8660254, 0. ], [0. , 0.8660254]]), array([[0. , 0.5], [0.5, 0. ]])] Kraus rank = 2
Application to a density matrix¶
Let us apply this channel to a density matrix:
density_matrix = np.zeros((2,2))
density_matrix[0,0] = 1.
result = my_channel.apply_to(density_matrix, [0])
print("result = ", result)
result = [[0.75 0. ] [0. 0.25]]
Composition of quantum channels¶
One can compose quantum channels. The cell below shows how to construct $\mathcal{E_1}\circ \mathcal{E_2}$:
Pauli_Z = np.array([[1.,0.],[0.,-1.]])
my_channel_2 = QuantumChannelKraus(kraus_operators=[np.sqrt(0.5)*np.identity(2), np.sqrt(0.5)*Pauli_Z],
name="my simple channel")
final_channel = my_channel*my_channel_2
print("Kraus rank of composition : ", final_channel.kraus_rank())
print("Kraus operators of composition : ", final_channel.kraus_operators)
Kraus rank of composition : 4 Kraus operators of composition : [array([[0.61237244, 0. ], [0. , 0.61237244]]), array([[ 0.61237244, 0. ], [ 0. , -0.61237244]]), array([[0. , 0.35355339], [0.35355339, 0. ]]), array([[ 0. , -0.35355339], [ 0.35355339, 0. ]])]