Construire des modèles de bruit
Versions des packages
Le code de cette page a été développé avec les dépendances suivantes. Nous recommandons d'utiliser ces versions ou des versions plus récentes.
qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
qiskit-aer~=0.17
Cette page montre comment utiliser le module noise de Qiskit Aer pour construire des modèles de bruit permettant de simuler des circuits quantiques en présence d'erreurs. C'est utile pour émuler des processeurs quantiques bruités et pour étudier les effets du bruit sur l'exécution d'algorithmes quantiques.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-aer qiskit-ibm-runtime
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Kraus, SuperOp
from qiskit.visualization import plot_histogram
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_aer import AerSimulator
# Import from Qiskit Aer noise module
from qiskit_aer.noise import (
NoiseModel,
QuantumError,
ReadoutError,
depolarizing_error,
pauli_error,
thermal_relaxation_error,
)
Le module noise de Qiskit Aer
Le module noise de Qiskit Aer contient des classes Python pour construire des modèles de bruit personnalisés pour la simulation. Il y a trois classes essentielles :
-
La classe
NoiseModelqui stocke un modèle de bruit utilisé pour la simulation bruitée. -
La classe
QuantumErrorqui décrit les erreurs de porte CPTP. Elles peuvent être appliquées :- Après les instructions gate ou reset
- Avant les instructions measure.
-
La classe
ReadoutErrorqui décrit les erreurs classiques de lecture.
Initialisation d'un modèle de bruit à partir d'un backend
Tu peux initialiser un modèle de bruit avec des paramètres issus des dernières données de calibration d'un backend physique :
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
backend = service.backend("ibm_fez")
noise_model = NoiseModel.from_backend(backend)
Cela produit un modèle de bruit qui approxime grossièrement les erreurs que l'on rencontrerait en utilisant ce backend. Si tu souhaites un contrôle plus fin sur les paramètres du modèle de bruit, tu devras créer ton propre modèle de bruit, comme décrit dans la suite de cette page.
Erreurs quantiques
Plutôt que de manipuler directement l'objet QuantumError, de nombreuses fonctions utilitaires existent pour générer automatiquement un type spécifique d'erreur quantique paramétrée. Elles sont contenues dans le module noise et couvrent de nombreux types d'erreurs couramment utilisés en recherche sur l'informatique quantique. Les noms des fonctions et le type d'erreur qu'elles retournent sont :
| Fonction d'erreur standard | Détails |
|---|---|
kraus_error | un canal d'erreur CPTP général à n qubits donné sous forme d'une liste de matrices de Kraus . |
mixed_unitary_error | une erreur unitaire mixte à n qubits donnée sous forme d'une liste de matrices unitaires et de probabilités . |
coherent_unitary_error | une erreur unitaire cohérente à n qubits donnée sous forme d'une seule matrice unitaire . |
pauli_error | un canal d'erreur de Pauli à n qubits (unitaire mixte) donné sous forme d'une liste de Pauli et de probabilités |
depolarizing_error | un canal d'erreur dépolarisant à n qubits paramétré par une probabilité de dépolarisation . |
reset_error | une erreur de reset à un seul qubit paramétrée par les probabilités de réinitialisation vers l'état , . |
thermal_relaxation_error | un canal de relaxation thermique à un seul qubit paramétré par les constantes de temps de relaxation , , le temps de porte , et la population thermique de l'état excité . |
phase_amplitude_damping_error | Un canal d'erreur d'amortissement de phase et d'amplitude combiné généralisé à un seul qubit, défini par un paramètre d'amortissement d'amplitude , un paramètre d'amortissement de phase , et une population thermique de l'état excité . |
amplitude_damping_error | Un canal d'erreur d'amortissement d'amplitude généralisé à un seul qubit, défini par un paramètre d'amortissement d'amplitude , et une population thermique de l'état excité . |
phase_damping_error | Un canal d'erreur d'amortissement de phase à un seul qubit défini par un paramètre d'amortissement de phase . |
Combinaison d'erreurs quantiques
Les instances de QuantumError peuvent être combinées en utilisant la composition, le produit tensoriel et l'expansion tensorielle (produit tensoriel en ordre inversé) pour produire de nouvelles QuantumErrors :
- Composition : avec
error = error1.compose(error2) - Produit tensoriel : avec
error = error1.tensor(error2) - Produit d'expansion : avec
error = error1.expand(error2)
Exemple
Pour construire une erreur de bit-flip à 5% sur un seul qubit :
# Construct a 1-qubit bit-flip and phase-flip errors
p_error = 0.05
bit_flip = pauli_error([("X", p_error), ("I", 1 - p_error)])
phase_flip = pauli_error([("Z", p_error), ("I", 1 - p_error)])
print(bit_flip)
print(phase_flip)
QuantumError on 1 qubits. Noise circuits:
P(0) = 0.05, Circuit =
┌───┐
q: ┤ X ├
└───┘
P(1) = 0.95, Circuit =
┌───┐
q: ┤ I ├
└───┘
QuantumError on 1 qubits. Noise circuits:
P(0) = 0.05, Circuit =
┌───┐
q: ┤ Z ├
└───┘
P(1) = 0.95, Circuit =
┌───┐
q: ┤ I ├
└───┘
# Compose two bit-flip and phase-flip errors
bitphase_flip = bit_flip.compose(phase_flip)
print(bitphase_flip)
QuantumError on 1 qubits. Noise circuits:
P(0) = 0.0025000000000000005, Circuit =
┌───┐┌───┐
q: ┤ X ├┤ Z ├
└───┘└───┘
P(1) = 0.0475, Circuit =
┌───┐┌───┐
q: ┤ X ├┤ I ├
└───┘└───┘
P(2) = 0.0475, Circuit =
┌───┐┌───┐
q: ┤ I ├┤ Z ├
└───┘└───┘
P(3) = 0.9025, Circuit =
┌───┐┌───┐
q: ┤ I ├┤ I ├
└───┘└───┘
# Tensor product two bit-flip and phase-flip errors with
# bit-flip on qubit-0, phase-flip on qubit-1
error2 = phase_flip.tensor(bit_flip)
print(error2)
QuantumError on 2 qubits. Noise circuits:
P(0) = 0.0025000000000000005, Circuit =
┌───┐
q_0: ┤ X ├
├───┤
q_1: ┤ Z ├
└───┘
P(1) = 0.0475, Circuit =
┌───┐
q_0: ┤ I ├
├───┤
q_1: ┤ Z ├
└───┘
P(2) = 0.0475, Circuit =
┌───┐
q_0: ┤ X ├
├───┤
q_1: ┤ I ├
└───┘
P(3) = 0.9025, Circuit =
┌───┐
q_0: ┤ I ├
├───┤
q_1: ┤ I ├
└───┘
Conversion vers et depuis des opérateurs QuantumChannel
On peut aussi convertir dans les deux sens entre les objets QuantumError de Qiskit Aer et les objets QuantumChannel de Qiskit.
# Convert to Kraus operator
bit_flip_kraus = Kraus(bit_flip)
print(bit_flip_kraus)
Kraus([[[-9.74679434e-01+0.j, 0.00000000e+00+0.j],
[ 0.00000000e+00+0.j, -9.74679434e-01+0.j]],
[[ 0.00000000e+00+0.j, 2.23606798e-01+0.j],
[ 2.23606798e-01+0.j, -4.96506831e-17+0.j]]],
input_dims=(2,), output_dims=(2,))
# Convert to Superoperator
phase_flip_sop = SuperOp(phase_flip)
print(phase_flip_sop)
SuperOp([[1. +0.j, 0. +0.j, 0. +0.j, 0. +0.j],
[0. +0.j, 0.9+0.j, 0. +0.j, 0. +0.j],
[0. +0.j, 0. +0.j, 0.9+0.j, 0. +0.j],
[0. +0.j, 0. +0.j, 0. +0.j, 1. +0.j]],
input_dims=(2,), output_dims=(2,))
# Convert back to a quantum error
print(QuantumError(bit_flip_kraus))
# Check conversion is equivalent to original error
QuantumError(bit_flip_kraus) == bit_flip
QuantumError on 1 qubits. Noise circuits:
P(0) = 1.0, Circuit =
┌───────┐
q: ┤ kraus ├
└───────┘
True
Erreur de lecture
Les erreurs classiques de lecture sont spécifiées par une liste de vecteurs de probabilités d'assignation :
- est la valeur du bit classique enregistrée
- est la valeur réelle du bit retournée par la mesure
Par exemple, pour un qubit : .
# Measurement misassignment probabilities
p0given1 = 0.1
p1given0 = 0.05
ReadoutError([[1 - p1given0, p1given0], [p0given1, 1 - p0given1]])
ReadoutError([[0.95 0.05]
[0.1 0.9 ]])
Les erreurs de lecture peuvent aussi être combinées avec compose, tensor et expand, tout comme les erreurs quantiques.
Ajouter des erreurs à un modèle de bruit
Lors de l'ajout d'une erreur quantique à un modèle de bruit, on doit spécifier le type d'instruction sur laquelle elle agit et les qubits auxquels l'appliquer. Il existe deux types d'erreurs quantiques :
- Erreur quantique sur tous les qubits
- Erreur quantique sur des qubits spécifiques
1. Erreur quantique sur tous les qubits
Cela applique la même erreur à chaque occurrence d'une instruction, quel que soit le qubit sur lequel elle agit.
Elle s'ajoute avec noise_model.add_all_qubit_quantum_error(error, instructions) :
# Create an empty noise model
noise_model = NoiseModel()
# Add depolarizing error to all single qubit u1, u2, u3 gates
error = depolarizing_error(0.05, 1)
noise_model.add_all_qubit_quantum_error(error, ["u1", "u2", "u3"])
# Print noise model info
print(noise_model)
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
Instructions with noise: ['u3', 'u2', 'u1']
All-qubits errors: ['u1', 'u2', 'u3']
2. Erreur quantique sur des qubits spécifiques
Cela applique l'erreur à chaque occurrence d'une instruction agissant sur une liste de qubits spécifiée. Remarque que l'ordre des qubits est important : par exemple, une erreur appliquée aux qubits [0, 1] pour une porte à deux qubits est différente de celle appliquée aux qubits [1, 0].
Elle s'ajoute avec noise_model.add_quantum_error(error, instructions, qubits) :
# Create an empty noise model
noise_model = NoiseModel()
# Add depolarizing error to all single qubit u1, u2, u3 gates on qubit 0 only
error = depolarizing_error(0.05, 1)
noise_model.add_quantum_error(error, ["u1", "u2", "u3"], [0])
# Print noise model info
print(noise_model)
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
Instructions with noise: ['u3', 'u2', 'u1']
Qubits with noise: [0]
Specific qubit errors: [('u1', (0,)), ('u2', (0,)), ('u3', (0,))]
Remarque sur les erreurs quantiques non locales
NoiseModel ne prend pas en charge l'ajout d'erreurs quantiques non locales sur des qubits. Elles doivent être gérées en dehors du NoiseModel. Cela suggère d'écrire ta propre passe de transpilation (TransformationPass) et d'exécuter cette passe juste avant le simulateur si tu dois insérer des erreurs quantiques dans ton circuit selon tes propres conditions.
Exécuter une simulation bruitée avec un modèle de bruit
La commande AerSimulator(noise_model=noise_model) renvoie un simulateur configuré selon le modèle de bruit donné. En plus de définir le modèle de bruit du simulateur, elle remplace également les portes de base du simulateur en fonction des portes du modèle de bruit.
Exemples de modèles de bruit
Nous allons maintenant donner quelques exemples de modèles de bruit. Pour nos démonstrations, nous utilisons un circuit de test simple générant un état GHZ à n qubits :
# System Specification
n_qubits = 4
circ = QuantumCircuit(n_qubits)
# Test Circuit
circ.h(0)
for qubit in range(n_qubits - 1):
circ.cx(qubit, qubit + 1)
circ.measure_all()
print(circ)
┌───┐ ░ ┌─┐
q_0: ┤ H ├──■─────────────░─┤M├─────────
└───┘┌─┴─┐ ░ └╥┘┌─┐
q_1: ─────┤ X ├──■────────░──╫─┤M├──────
└───┘┌─┴─┐ ░ ║ └╥┘┌─┐
q_2: ──────────┤ X ├──■───░──╫──╫─┤M├───
└───┘┌─┴─┐ ░ ║ ║ └╥┘┌─┐
q_3: ───────────────┤ X ├─░──╫──╫──╫─┤M├
└───┘ ░ ║ ║ ║ └╥┘
meas: 4/════════════════════════╩══╩══╩══╩═
0 1 2 3
Simulation idéale
# Ideal simulator and execution
sim_ideal = AerSimulator()
result_ideal = sim_ideal.run(circ).result()
plot_histogram(result_ideal.get_counts(0))
Exemple de bruit 1 : modèle de bruit simple à bit-flip
Considérons un exemple de modèle de bruit simplifié, courant en recherche sur la théorie de l'information quantique :
- Lors de l'application d'une porte à un seul qubit, l'état du qubit est inversé avec la probabilité
p_gate1. - Lors de l'application d'une porte à deux qubits, des erreurs sur un seul qubit sont appliquées à chaque qubit.
- Lors de la réinitialisation d'un qubit, le qubit est réinitialisé à 1 au lieu de 0 avec la probabilité
p_reset. - Lors de la mesure d'un qubit, l'état du qubit est inversé avec la probabilité
p_meas.
# Example error probabilities
p_reset = 0.03
p_meas = 0.1
p_gate1 = 0.05
# QuantumError objects
error_reset = pauli_error([("X", p_reset), ("I", 1 - p_reset)])
error_meas = pauli_error([("X", p_meas), ("I", 1 - p_meas)])
error_gate1 = pauli_error([("X", p_gate1), ("I", 1 - p_gate1)])
error_gate2 = error_gate1.tensor(error_gate1)
# Add errors to noise model
noise_bit_flip = NoiseModel()
noise_bit_flip.add_all_qubit_quantum_error(error_reset, "reset")
noise_bit_flip.add_all_qubit_quantum_error(error_meas, "measure")
noise_bit_flip.add_all_qubit_quantum_error(error_gate1, ["u1", "u2", "u3"])
noise_bit_flip.add_all_qubit_quantum_error(error_gate2, ["cx"])
print(noise_bit_flip)
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
Instructions with noise: ['u3', 'u2', 'measure', 'cx', 'reset', 'u1']
All-qubits errors: ['reset', 'measure', 'u1', 'u2', 'u3', 'cx']
Exécuter la simulation bruitée
# Create noisy simulator backend
sim_noise = AerSimulator(noise_model=noise_bit_flip)
# Transpile circuit for noisy basis gates
passmanager = generate_preset_pass_manager(
optimization_level=3, backend=sim_noise
)
circ_tnoise = passmanager.run(circ)
# Run and get counts
result_bit_flip = sim_noise.run(circ_tnoise).result()
counts_bit_flip = result_bit_flip.get_counts(0)
# Plot noisy output
plot_histogram(counts_bit_flip)
Exemple 2 : relaxation thermique T1/T2
Considérons maintenant un modèle d'erreur plus réaliste basé sur la relaxation thermique avec l'environnement du qubit :
- Chaque qubit est paramétré par une constante de temps de relaxation thermique et une constante de temps de déphasage .
- Remarque que l'on doit avoir .
- Les taux d'erreur sur les instructions sont déterminés par les temps de porte et les valeurs , des qubits.
# T1 and T2 values for qubits 0-3
T1s = np.random.normal(
50e3, 10e3, 4
) # Sampled from normal distribution mean 50 microsec
T2s = np.random.normal(
70e3, 10e3, 4
) # Sampled from normal distribution mean 50 microsec
# Truncate random T2s <= T1s
T2s = np.array([min(T2s[j], 2 * T1s[j]) for j in range(4)])
# Instruction times (in nanoseconds)
time_u1 = 0 # virtual gate
time_u2 = 50 # (single X90 pulse)
time_u3 = 100 # (two X90 pulses)
time_cx = 300
time_reset = 1000 # 1 microsecond
time_measure = 1000 # 1 microsecond
# QuantumError objects
errors_reset = [
thermal_relaxation_error(t1, t2, time_reset) for t1, t2 in zip(T1s, T2s)
]
errors_measure = [
thermal_relaxation_error(t1, t2, time_measure) for t1, t2 in zip(T1s, T2s)
]
errors_u1 = [
thermal_relaxation_error(t1, t2, time_u1) for t1, t2 in zip(T1s, T2s)
]
errors_u2 = [
thermal_relaxation_error(t1, t2, time_u2) for t1, t2 in zip(T1s, T2s)
]
errors_u3 = [
thermal_relaxation_error(t1, t2, time_u3) for t1, t2 in zip(T1s, T2s)
]
errors_cx = [
[
thermal_relaxation_error(t1a, t2a, time_cx).expand(
thermal_relaxation_error(t1b, t2b, time_cx)
)
for t1a, t2a in zip(T1s, T2s)
]
for t1b, t2b in zip(T1s, T2s)
]
# Add errors to noise model
noise_thermal = NoiseModel()
for j in range(4):
noise_thermal.add_quantum_error(errors_reset[j], "reset", [j])
noise_thermal.add_quantum_error(errors_measure[j], "measure", [j])
noise_thermal.add_quantum_error(errors_u1[j], "u1", [j])
noise_thermal.add_quantum_error(errors_u2[j], "u2", [j])
noise_thermal.add_quantum_error(errors_u3[j], "u3", [j])
for k in range(4):
noise_thermal.add_quantum_error(errors_cx[j][k], "cx", [j, k])
print(noise_thermal)
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u2', 'u3']
Instructions with noise: ['u3', 'u2', 'measure', 'cx', 'reset']
Qubits with noise: [0, 1, 2, 3]
Specific qubit errors: [('reset', (0,)), ('reset', (1,)), ('reset', (2,)), ('reset', (3,)), ('measure', (0,)), ('measure', (1,)), ('measure', (2,)), ('measure', (3,)), ('u2', (0,)), ('u2', (1,)), ('u2', (2,)), ('u2', (3,)), ('u3', (0,)), ('u3', (1,)), ('u3', (2,)), ('u3', (3,)), ('cx', (0, 0)), ('cx', (0, 1)), ('cx', (0, 2)), ('cx', (0, 3)), ('cx', (1, 0)), ('cx', (1, 1)), ('cx', (1, 2)), ('cx', (1, 3)), ('cx', (2, 0)), ('cx', (2, 1)), ('cx', (2, 2)), ('cx', (2, 3)), ('cx', (3, 0)), ('cx', (3, 1)), ('cx', (3, 2)), ('cx', (3, 3))]
Exécuter la simulation bruitée
# Run the noisy simulation
sim_thermal = AerSimulator(noise_model=noise_thermal)
# Transpile circuit for noisy basis gates
passmanager = generate_preset_pass_manager(
optimization_level=3, backend=sim_thermal
)
circ_tthermal = passmanager.run(circ)
# Run and get counts
result_thermal = sim_thermal.run(circ_tthermal).result()
counts_thermal = result_thermal.get_counts(0)
# Plot noisy output
plot_histogram(counts_thermal)
Prochaines étapes
- Pour simuler des circuits bruités, consulte Simulation exacte et bruitée avec les primitives Qiskit Aer.
- Consulte la référence du module noise de Qiskit Aer.