Noisy Simulations

Quantum systems are subject to noise during computations, from the application of gates, imperfect measurements, or interactions with the environment. Being able to simulate and validate quantum algorithms in a noisy setup is crucial for achieving any advantage on current NISQ machines. This section provides an overview of how noise models are instantiated, how target qubits and gates are specified, and the predefined noise models.

We strongly encourage the user to have a look at the dedicated notebook, where all the details of the manipulation, use, and simulation of noise models are presented.

For more details on how to use noise models taken from real hardware, you can look at Simulated Devices.

from mpqp.noise import *

Note

Noisy simulations are supported for IBMDevice, AtosDevice and AWSDevice.

Noise models

In order to represent a general noise model, we introduce the abstract class NoiseModel. This class regroups all the attributes and methods common to all predefined noise models.

While currently abstract, the class is designed with extensibility in mind to support parameterized noise models in the future. This feature will enable users to define noise models with adjustable parameters, offering greater flexibility in simulating and analyzing the effects of noise on quantum circuits.

class NoiseModel(targets=None, gates=None)[source]

Bases: ABC

Abstract class used to represent a generic noise model, specifying criteria for applying different noise types to a quantum circuit or some of its qubits.

This class allows one to specify which qubits (targets) and which gates of the circuit will be affected by this noise model. If you do not specify a target, the operation will apply to all qubits.

Parameters
  • targets (Optional[list[int]]) – Qubits affected by this noise. Defaults to all qubits.

  • gates (Optional[list[type[NativeGate]]]) – Gates affected by this noise. Defaults to all gates.

Raises

ValueError – When the target list is empty, or the target indices are duplicated or negative. When the size of the gate is higher than the number of target qubits.

connections()[source]

Qubits to which this is connected (applied to).

Return type

set[int]

info()[source]

For usage of pretty prints, this method displays in a string all information relevant to the noise at matter.

Returns

The string displaying the noise information in a human readable manner.

Return type

str

to_adjusted_kraus_operators(targets, size)[source]

In some cases, you may prefer the Kraus operators to match the size of your circuit, and the targets involved. In particular, the targets of the noise application may not match the noise targets, because the noise targets signifies all the qubits that the noise is applicable on, but if the noise happens at a gate execution, it would only actually impact the targets qubits of the gate.

Note

This generic method considers that the default Kraus operators of the noise are for one qubit noises. If this is not the case, this method should be overloaded in the corresponding class.

Parameters
  • targets (set[int]) – Qubits actually affected by the noise.

  • size (int) – Size of the desired Kraus operators.

Returns

The Kraus operators adjusted to the targets of the gate on which the noise acts and the size of the circuit.

Return type

list[npt.NDArray[np.complex64]]

to_kraus_operators()[source]

Noise models can be represented by Kraus operators. They represent how the state is affected by the noise following the formula

\(\rho \leftarrow \sum_{K \in \mathcal{K}} K \rho K^\dagger\)

Where \(\mathcal{K}\) is the set of Kraus operators corresponding to the noise model and \(\rho\) is the state (as a density matrix).

Returns

The Kraus operators of the noise. Note that it is not a unique representation.

Return type

list[npt.NDArray[np.complex64]]

to_other_language(language)[source]

Transforms this noise model into the corresponding object in the language specified in the language arg.

In the current version, only Braket and my_QLM are available for conversion.

Parameters

language (Language) – Enum representing the target language.

Returns

The corresponding noise model (or channel) in the target language.

Return type

BraketNoise | QLMNoise | QuantumError

gates

See parameter description.

targets

See parameter description.

Depolarizing Noise Model

class Depolarizing(prob, targets=None, dimension=1, gates=None)[source]

Bases: DimensionalNoiseModel

Class representing the depolarizing noise channel, which maps a state onto a linear combination of itself and the maximally mixed state. It can be applied to a single or multiple qubits, and depends on a single parameter (probability or error rate).

When the number of qubits in the target is higher than the dimension, the noise will be applied to all possible combinations of indices of size dimension.

Parameters
  • prob (float) – Depolarizing error probability (also called error rate).

  • targets (Optional[list[int]]) – Qubits affected by this noise. Defaults to all qubits.

  • dimension (int) – Dimension of the depolarizing channel.

  • gates (Optional[list[type[NativeGate]]]) – Gates affected by this noise. Defaults to all gates.

Raises

ValueError – When a wrong dimension (negative) or probability (outside of the expected interval) is input. When the size of the specified gates is not consistent with the number of targets or the dimension.

Examples

>>> circuit = QCircuit([H(i) for i in range(3)])
>>> d1 = Depolarizing(0.32, list(range(circuit.nb_qubits)))
>>> d2 = Depolarizing(0.01)
>>> d3 = Depolarizing(0.05, [0, 1], dimension=2)
>>> d4 = Depolarizing(0.12, [2], gates=[H, Rx, Ry, Rz])
>>> d5 = Depolarizing(0.05, [0, 1, 2], dimension=2, gates=[CNOT, CZ])
>>> circuit.add([d1, d2, d3, d4, d5])
>>> print(circuit)  
     ┌───┐
q_0: ┤ H ├
     ├───┤
q_1: ┤ H ├
     ├───┤
q_2: ┤ H ├
     └───┘
NoiseModel:
    Depolarizing(0.32, [0, 1, 2])
    Depolarizing(0.01)
    Depolarizing(0.05, [0, 1], dimension=2)
    Depolarizing(0.12, [2], gates=[H, Rx, Ry, Rz])
    Depolarizing(0.05, [0, 1, 2], dimension=2, gates=[CNOT, CZ])
>>> print(circuit.to_other_language(Language.BRAKET))  
T  : │                        0                         │
      ┌───┐ ┌────────────┐ ┌────────────┐
q0 : ─┤ H ├─┤ DEPO(0.01) ├─┤ DEPO(0.32) ├────────────────
      └───┘ └────────────┘ └────────────┘
      ┌───┐ ┌────────────┐ ┌────────────┐
q1 : ─┤ H ├─┤ DEPO(0.01) ├─┤ DEPO(0.32) ├────────────────
      └───┘ └────────────┘ └────────────┘
      ┌───┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
q2 : ─┤ H ├─┤ DEPO(0.12) ├─┤ DEPO(0.01) ├─┤ DEPO(0.32) ├─
      └───┘ └────────────┘ └────────────┘ └────────────┘
T  : │                        0                         │
info()[source]

For usage of pretty prints, this method displays in a string all information relevant to the noise at matter.

Returns

The string displaying the noise information in a human readable manner.

Return type

str

to_kraus_operators()[source]

Noise models can be represented by Kraus operators. They represent how the state is affected by the noise following the formula

\(\rho \leftarrow \sum_{K \in \mathcal{K}} K \rho K^\dagger\)

Where \(\mathcal{K}\) is the set of Kraus operators corresponding to the noise model and \(\rho\) is the state (as a density matrix).

Returns

The Kraus operators of the noise. Note that it is not a unique representation.

Return type

list[npt.NDArray[np.complex64]]

to_other_language(language=Language.QISKIT)[source]

See the documentation for this method in the abstract mother class NoiseModel.

Parameters

language (Language) – Enum representing the target language.

Return type

BraketNoise | TwoQubitDepolarizing | QLMNoise | QuantumError

Examples

>>> Depolarizing(0.3, [0,1], dimension=1).to_other_language(Language.BRAKET)
Depolarizing('probability': 0.3, 'qubit_count': 1)
>>> Depolarizing(0.3, [0,1], dimension=1).to_other_language(Language.QISKIT).to_quantumchannel()
SuperOp([[0.85+0.j, 0.  +0.j, 0.  +0.j, 0.15+0.j],
         [0.  +0.j, 0.7 +0.j, 0.  +0.j, 0.  +0.j],
         [0.  +0.j, 0.  +0.j, 0.7 +0.j, 0.  +0.j],
         [0.15+0.j, 0.  +0.j, 0.  +0.j, 0.85+0.j]],
        input_dims=(2,), output_dims=(2,))
>>> print(Depolarizing(0.3, [0,1], dimension=1).to_other_language(Language.MY_QLM))  
Depolarizing channel, p = 0.3:
[[0.83666003 0.        ]
 [0.         0.83666003]]
[[0.        +0.j 0.31622777+0.j]
 [0.31622777+0.j 0.        +0.j]]
[[0.+0.j         0.-0.31622777j]
 [0.+0.31622777j 0.+0.j        ]]
[[ 0.31622777+0.j  0.        +0.j]
 [ 0.        +0.j -0.31622777+0.j]]
prob

Probability or error rate of the depolarizing noise model.

BitFlip Noise Model

class BitFlip(prob, targets=None, gates=None)[source]

Bases: NoiseModel

Class representing the bit flip noise channel, which flips the state of a qubit with a certain probability. It can be applied to single and multi-qubit gates and depends on a single parameter (probability or error rate).

Parameters
  • prob (float) – Bit flip error probability or error rate (must be within [0, 0.5]).

  • targets (Optional[list[int]]) – Qubits affected by this noise. Defaults to all qubits.

  • gates (Optional[list[type[NativeGate]]]) – Gates affected by this noise. If multi-qubit gates is passed, single-qubit bitflip will be added for each qubit connected (target, control) with the gates. Defaults to all gates.

Raises

ValueError – When the probability is outside of the expected interval [0, 0.5].

Examples

>>> circuit = QCircuit(
...     [H(i) for i in range(3)]
...     + [
...         BitFlip(0.1, [0]),
...         BitFlip(0.3, [1, 2]),
...         BitFlip(0.05, [0], gates=[H]),
...         BitFlip(0.3),
...     ]
... )
>>> print(circuit)
     ┌───┐
q_0: ┤ H ├
     ├───┤
q_1: ┤ H ├
     ├───┤
q_2: ┤ H ├
     └───┘
NoiseModel:
    BitFlip(0.1, [0])
    BitFlip(0.3, [1, 2])
    BitFlip(0.05, [0], gates=[H])
    BitFlip(0.3)
>>> print(circuit.to_other_language(Language.BRAKET)) 
T  : │                    0                     │
      ┌───┐ ┌─────────┐ ┌──────────┐ ┌─────────┐
q0 : ─┤ H ├─┤ BF(0.3) ├─┤ BF(0.05) ├─┤ BF(0.1) ├─
      └───┘ └─────────┘ └──────────┘ └─────────┘
      ┌───┐ ┌─────────┐ ┌─────────┐
q1 : ─┤ H ├─┤ BF(0.3) ├─┤ BF(0.3) ├──────────────
      └───┘ └─────────┘ └─────────┘
      ┌───┐ ┌─────────┐ ┌─────────┐
q2 : ─┤ H ├─┤ BF(0.3) ├─┤ BF(0.3) ├──────────────
      └───┘ └─────────┘ └─────────┘
T  : │                    0                     │
info()[source]

For usage of pretty prints, this method displays in a string all information relevant to the noise at matter.

Returns

The string displaying the noise information in a human readable manner.

Return type

str

to_kraus_operators()[source]

Noise models can be represented by Kraus operators. They represent how the state is affected by the noise following the formula

\(\rho \leftarrow \sum_{K \in \mathcal{K}} K \rho K^\dagger\)

Where \(\mathcal{K}\) is the set of Kraus operators corresponding to the noise model and \(\rho\) is the state (as a density matrix).

Returns

The Kraus operators of the noise. Note that it is not a unique representation.

Return type

list[npt.NDArray[np.complex64]]

to_other_language(language=Language.QISKIT)[source]

See documentation of this method in abstract mother class NoiseModel.

Parameters

language (Language) – Enum representing the target language.

Return type

BraketNoise | QLMNoise | QuantumError

Examples

>>> BitFlip(0.3, [0,1]).to_other_language(Language.BRAKET)
BitFlip('probability': 0.3, 'qubit_count': 1)
>>> BitFlip(0.3, [0,1]).to_other_language(Language.QISKIT).to_quantumchannel()
SuperOp([[0.7+0.j, 0. +0.j, 0. +0.j, 0.3+0.j],
         [0. +0.j, 0.7+0.j, 0.3+0.j, 0. +0.j],
         [0. +0.j, 0.3+0.j, 0.7+0.j, 0. +0.j],
         [0.3+0.j, 0. +0.j, 0. +0.j, 0.7+0.j]],
        input_dims=(2,), output_dims=(2,))
prob

See parameter description.

Amplitude Damping Noise Model

class AmplitudeDamping(gamma, prob=1, targets=None, gates=None)[source]

Bases: NoiseModel

Class representing the amplitude damping noise channel, which can model both the standard and generalized amplitude damping processes. It can be applied to a single qubit and depends on two parameters: the decay rate gamma and the probability of excitation prob.

We recall below the associated representation, in terms of Kraus operators, where we denote by \(\gamma\) the decay rate gamma, and by \(p\) the excitation probability prob:

\(E_0=\sqrt{p}\begin{pmatrix}1&0\\0&\sqrt{1-\gamma}\end{pmatrix}\), \(~ ~ E_1=\sqrt{p}\begin{pmatrix}0&\sqrt{\gamma}\\0&0\end{pmatrix}\), \(~ ~ E_2=\sqrt{1-p}\begin{pmatrix}\sqrt{1-\gamma}&0\\0&1\end{pmatrix}\) and \(~ E_3=\sqrt{1-p}\begin{pmatrix}0&0\\\sqrt{\gamma}&0\end{pmatrix}\).

Parameters
  • gamma (float) – Decaying rate of the amplitude damping noise channel.

  • prob (float) – Probability of excitation in the generalized amplitude damping noise channel. A value of 1, corresponds to the standard amplitude damping. It must be in the [0, 1] interval.

  • targets (Optional[list[int]]) – Qubits affected by this noise. Defaults to all qubits.

  • gates (Optional[list[type[NativeGate]]]) – Gates affected by this noise. Defaults to all gates.

Raises

ValueError – When the gamma or prob parameters are outside of the expected interval [0, 1].

Examples

>>> circuit = QCircuit(
...     [H(i) for i in range(3)]
...     + [
...         AmplitudeDamping(0.2, 0, [0]),
...         AmplitudeDamping(0.4, 0.1, [1, 2]),
...         AmplitudeDamping(0.1, 1, [0, 1, 2]),
...         AmplitudeDamping(0.1, 1),
...         AmplitudeDamping(0.7, targets=[0, 1]),
...     ]
... )
>>> print(circuit)
     ┌───┐
q_0: ┤ H ├
     ├───┤
q_1: ┤ H ├
     ├───┤
q_2: ┤ H ├
     └───┘
NoiseModel:
    AmplitudeDamping(0.2, 0, targets=[0])
    AmplitudeDamping(0.4, 0.1, targets=[1, 2])
    AmplitudeDamping(0.1, targets=[0, 1, 2])
    AmplitudeDamping(0.1)
    AmplitudeDamping(0.7, targets=[0, 1])
>>> print(circuit.to_other_language(Language.BRAKET)) 
T  : │                               0                               │
      ┌───┐ ┌─────────┐ ┌─────────┐   ┌─────────┐     ┌────────────┐
q0 : ─┤ H ├─┤ AD(0.7) ├─┤ AD(0.1) ├───┤ AD(0.1) ├─────┤ GAD(0.2,0) ├──
      └───┘ └─────────┘ └─────────┘   └─────────┘     └────────────┘
      ┌───┐ ┌─────────┐ ┌─────────┐   ┌─────────┐    ┌──────────────┐
q1 : ─┤ H ├─┤ AD(0.7) ├─┤ AD(0.1) ├───┤ AD(0.1) ├────┤ GAD(0.4,0.1) ├─
      └───┘ └─────────┘ └─────────┘   └─────────┘    └──────────────┘
      ┌───┐ ┌─────────┐ ┌─────────┐ ┌──────────────┐
q2 : ─┤ H ├─┤ AD(0.1) ├─┤ AD(0.1) ├─┤ GAD(0.4,0.1) ├──────────────────
      └───┘ └─────────┘ └─────────┘ └──────────────┘
T  : │                               0                               │
info()[source]

For usage of pretty prints, this method displays in a string all information relevant to the noise at matter.

Returns

The string displaying the noise information in a human readable manner.

Return type

str

to_kraus_operators()[source]

Noise models can be represented by Kraus operators. They represent how the state is affected by the noise following the formula

\(\rho \leftarrow \sum_{K \in \mathcal{K}} K \rho K^\dagger\)

Where \(\mathcal{K}\) is the set of Kraus operators corresponding to the noise model and \(\rho\) is the state (as a density matrix).

Returns

The Kraus operators of the noise. Note that it is not a unique representation.

Return type

list[npt.NDArray[np.complex64]]

to_other_language(language=Language.QISKIT)[source]

See documentation of this method in abstract mother class NoiseModel.

Parameters

language (Language) – Enum representing the target language.

Return type

BraketNoise | QLMNoise | QuantumError

Examples

>>> AmplitudeDamping(0.4, targets=[0, 1]).to_other_language(Language.BRAKET)
AmplitudeDamping('gamma': 0.4, 'qubit_count': 1)
>>> AmplitudeDamping(0.4, 0.2, [1]).to_other_language(Language.BRAKET)
GeneralizedAmplitudeDamping('gamma': 0.4, 'probability': 0.2, 'qubit_count': 1)
>>> AmplitudeDamping(0.2, 0.4, [0, 1]).to_other_language(Language.QISKIT).to_quantumchannel()
SuperOp([[0.88      +0.j, 0.        +0.j, 0.        +0.j, 0.08      +0.j],
         [0.        +0.j, 0.89442719+0.j, 0.        +0.j, 0.        +0.j],
         [0.        +0.j, 0.        +0.j, 0.89442719+0.j, 0.        +0.j],
         [0.12      +0.j, 0.        +0.j, 0.        +0.j, 0.92      +0.j]],
        input_dims=(2,), output_dims=(2,))
gamma

See parameter description.

prob

See parameter description.

Phase Damping Noise Model

class PhaseDamping(gamma, targets=None, gates=None)[source]

Bases: NoiseModel

Class representing the phase damping noise channel. It can be applied to a single qubit and depends on the phase damping parameter gamma. Phase damping happens when a quantum system loses its phase information due to interactions with the environment, leading to decoherence.

Parameters
  • gamma (float) – Probability of phase damping.

  • targets (Optional[list[int]]) – Qubits affected by this noise. Defaults to all qubits.

  • gates (Optional[list[type[NativeGate]]]) – Gates affected by this noise. Defaults to all gates.

Raises

ValueError – When the gamma parameter is outside of the expected interval [0, 1].

Examples

>>> circuit = QCircuit(
...     [H(i) for i in range(3)]
...     + [
...         PhaseDamping(0.32, list(range(3))),
...         PhaseDamping(0.01),
...         PhaseDamping(0.45, [0, 1]),
...     ]
... )
>>> print(circuit)
     ┌───┐
q_0: ┤ H ├
     ├───┤
q_1: ┤ H ├
     ├───┤
q_2: ┤ H ├
     └───┘
NoiseModel:
    PhaseDamping(0.32, [0, 1, 2])
    PhaseDamping(0.01)
    PhaseDamping(0.45, [0, 1])
>>> print(circuit.to_other_language(Language.BRAKET)) 
T  : │                     0                      │
      ┌───┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
q0 : ─┤ H ├─┤ PD(0.45) ├─┤ PD(0.01) ├─┤ PD(0.32) ├─
      └───┘ └──────────┘ └──────────┘ └──────────┘
      ┌───┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
q1 : ─┤ H ├─┤ PD(0.45) ├─┤ PD(0.01) ├─┤ PD(0.32) ├─
      └───┘ └──────────┘ └──────────┘ └──────────┘
      ┌───┐ ┌──────────┐ ┌──────────┐
q2 : ─┤ H ├─┤ PD(0.01) ├─┤ PD(0.32) ├──────────────
      └───┘ └──────────┘ └──────────┘
T  : │                     0                      │
info()[source]

For usage of pretty prints, this method displays in a string all information relevant to the noise at matter.

Returns

The string displaying the noise information in a human readable manner.

Return type

str

to_kraus_operators()[source]

Noise models can be represented by Kraus operators. They represent how the state is affected by the noise following the formula

\(\rho \leftarrow \sum_{K \in \mathcal{K}} K \rho K^\dagger\)

Where \(\mathcal{K}\) is the set of Kraus operators corresponding to the noise model and \(\rho\) is the state (as a density matrix).

Returns

The Kraus operators of the noise. Note that it is not a unique representation.

Return type

list[npt.NDArray[np.complex64]]

to_other_language(language=Language.QISKIT)[source]

See documentation of this method in abstract mother class NoiseModel.

Parameters

language (Language) – Enum representing the target language.

Return type

BraketNoise | QLMNoise | QuantumError

Examples

>>> PhaseDamping(0.4, [0, 1]).to_other_language(Language.BRAKET)
PhaseDamping('gamma': 0.4, 'qubit_count': 1)
>>> PhaseDamping(0.4, [0, 1]).to_other_language(Language.QISKIT).to_quantumchannel()
SuperOp([[1.        +0.j, 0.        +0.j, 0.        +0.j, 0.        +0.j],
         [0.        +0.j, 0.77459667+0.j, 0.        +0.j, 0.        +0.j],
         [0.        +0.j, 0.        +0.j, 0.77459667+0.j, 0.        +0.j],
         [0.        +0.j, 0.        +0.j, 0.        +0.j, 1.        +0.j]],
        input_dims=(2,), output_dims=(2,))
>>> print(PhaseDamping(0.4, [0, 1]).to_other_language(Language.MY_QLM))  
Phase Damping channel, gamma = 0.4:
[[1.         0.        ]
 [0.         0.77459667]]
[[0.         0.        ]
 [0.         0.77459667]]
gamma

Probability of phase damping.