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$.

In [1]:
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:

In [2]:
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}$:

In [3]:
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.        ]])]