Lärmmodelle erstellen
Der Code auf dieser Seite wurde unter Berücksichtigung der folgenden Anforderungen entwickelt. Wir empfehlen die Verwendung dieser oder neuerer Versionen.
qiskit[all]~=2.5.2 qiskit-ibm-runtime~=0.47.0 qiskit-aer~=0.17
Diese Seite zeigt, wie man mit dem Qiskit Aer noise modul zur Erstellung von Rauschmodellen für die Simulation von Quantenschaltungen in Anwesenheit von Fehlern. Dies ist nützlich für die Emulation verrauschter Quantenprozessoren und für die Untersuchung der Auswirkungen von Rauschen auf die Ausführung von Quantenalgorithmen.
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,
)Qiskit noise Aer-Modul
Das Modul Qiskit Aer noise enthält Python Klassen, um maßgeschneiderte Geräuschmodelle für die Simulation zu erstellen. Es gibt drei Schlüsselklassen:
-
Die Klasse
NoiseModelspeichert ein Rauschmodell, das für die Rauschsimulation verwendet wird. -
Die Klasse
QuantumError, die CPTP-Gate-Fehler beschreibt. Diese können angewendet werden:- Nach Tor- oder Reset-Anweisungen
- Anweisungen vor der Messung.
-
Die Klasse
ReadoutError, die klassische Auslesefehler beschreibt.
Ein Rauschmodell aus einem Backend initialisieren
Sie können ein Rauschmodell mit Parametern initialisieren, die auf der Grundlage der aktuellsten Kalibrierungsdaten für ein physikalisches Backend festgelegt wurden.
In diesen Beispielen wird das FakeSherbrooke``qiskit_ibm_runtime Mock-Backend von verwendet, Sie können es jedoch mit jedem Qiskit-kompatiblen echten oder simulierten Backend ausprobieren.
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
backend = FakeSherbrooke()
noise_model = NoiseModel.from_backend(backend)Dies führt zu einem Rauschmodell, das die Fehler, die bei der Verwendung dieses Backends auftreten würden, annähernd wiedergibt. Wenn Sie eine detailliertere Kontrolle über die Parameter des Rauschmodells haben möchten, müssen Sie Ihr eigenes Rauschmodell erstellen, wie im Rest dieser Seite beschrieben.
Quantenfehler
Anstatt direkt mit dem QuantumError Objekt zu arbeiten, gibt es viele Hilfsfunktionen, die automatisch einen bestimmten Typ von parametrisiertem Quantenfehler generieren. Diese sind im noise Modul enthalten und umfassen Funktionen für viele gängige Fehlertypen, die in der Quantencomputerforschung verwendet werden. Die Funktionsnamen und die Art der Fehler, die sie zurückgeben, sind:
Standardfehlerfunktion | Details zu |
|---|---|
kraus_error | einen allgemeinen n-Qubit-CPTP-Fehlerkanal in Form einer Liste von Kraus-Matrizen . |
mixed_unitary_error | einen n-qubit gemischten unitären Fehler, der als eine Liste von unitären Matrizen und Wahrscheinlichkeiten angegeben wird . |
coherent_unitary_error | ein n-Qubit kohärenter unitärer Fehler, der als eine einzige unitäre Matrix gegeben ist. |
pauli_error | ein n-Qubit-Pauli-Fehlerkanal (gemischt unitär), der als Liste von Pauli und Wahrscheinlichkeiten angegeben ist |
depolarizing_error | einen n-qubit depolarisierenden Fehlerkanal, der durch eine Depolarisationswahrscheinlichkeit parametrisiert ist. |
reset_error | ein Einzelqubit-Reset-Fehler, parametrisiert durch die Wahrscheinlichkeiten eines Resets in den Zustand . |
thermal_relaxation_error | ein thermischer Relaxationskanal für ein einzelnes Qubit, parametrisiert durch die Relaxationszeitkonstanten , , die Torzeit und die thermische Population im angeregten Zustand . |
phase_amplitude_damping_error | Ein verallgemeinerter kombinierter Phasen- und Amplitudendämpfungs-Fehlerkanal, der durch einen Amplitudendämpfungsparameter , einen Phasendämpfungsparameter und eine thermische Population im angeregten Zustand gegeben ist. |
amplitude_damping_error | Ein verallgemeinerter Amplitudendämpfungs-Fehlerkanal, der durch einen Amplitudendämpfungsparameter und eine thermische Population im angeregten Zustand gegeben ist. |
phase_damping_error | Ein Einzelqubit-Phasendämpfungsfehlerkanal, der durch einen Phasendämpfungs-Parameter gegeben ist. |
Quantenfehler kombinieren
QuantumError instanzen können mit Hilfe von Komposition, Tensorprodukt und Tensorexpansion (Tensorprodukt umgekehrter Ordnung) kombiniert werden, um neue QuantumErrors zu erzeugen:
- Zusammensetzung: als
error = error1.compose(error2) - Tensorprodukt: als
error = error1.tensor(error2) - Produkt erweitern: als
error = error1.expand(error2)
Beispiel
Konstruktion eines 5%igen Ein-Qubit-Bitflip-Fehlers:
# 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)Output:
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)Output:
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)Output:
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 ├
└───┘
In und aus Operatoren des „ QuantumChannel “ konvertieren
Wir können auch zwischen QuantumError Objekten in Qiskit Aer und QuantumChannel Objekten in Qiskit hin und her konvertieren.
# Convert to Kraus operator
bit_flip_kraus = Kraus(bit_flip)
print(bit_flip_kraus)Output:
Kraus([[[-9.74679434e-01+1.19363805e-16j,
0.00000000e+00+0.00000000e+00j],
[ 0.00000000e+00+0.00000000e+00j,
-9.74679434e-01+0.00000000e+00j]],
[[ 0.00000000e+00+0.00000000e+00j,
4.69834045e-18-2.23606798e-01j],
[-2.26855945e-17-2.23606798e-01j,
5.03721386e-33+4.96506831e-17j]]],
input_dims=(2,), output_dims=(2,))
# Convert to Superoperator
phase_flip_sop = SuperOp(phase_flip)
print(phase_flip_sop)Output:
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_flipOutput:
QuantumError on 1 qubits. Noise circuits:
P(0) = 1.0, Circuit =
┌───────┐
q: ┤ kraus ├
└───────┘
True
Auslesungsfehler
Klassische Auslesungsfehler werden durch eine Liste von Zuordnungswahrscheinlichkeitsvektoren angegeben :
- ist der aufgezeichnete klassische Bitwert
- ist der wahre Bitwert, der von der Messung zurückgegeben wird
Zum Beispiel für ein Qubit: .
# Measurement misassignment probabilities
p0given1 = 0.1
p1given0 = 0.05
ReadoutError([[1 - p1given0, p1given0], [p0given1, 1 - p0given1]])Output:
ReadoutError([[0.95 0.05]
[0.1 0.9 ]])
Auslesefehler können auch mit compose, tensor und expand kombiniert werden, wie bei Quantenfehlern.
Fehler zu einem Rauschmodell hinzufügen
Wenn man einen Quantenfehler zu einem Rauschmodell hinzufügt, muss man angeben, auf welche Art von Anweisung er wirkt und auf welche Qubits er angewendet werden soll. Es gibt zwei Fälle von Quantenfehlern:
- All-Qubit-Quantenfehler
- Spezifischer Qubit-Quantenfehler
1. All-Qubit-Quantenfehler
Dadurch wird bei jedem Auftreten eines Befehls derselbe Fehler verursacht, unabhängig davon, auf welche Qubits er wirkt.
Sie wird als noise_model.add_all_qubit_quantum_error(error, instructions) hinzugefügt:
# 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)Output:
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
Instructions with noise: ['u2', 'u3', 'u1']
All-qubits errors: ['u1', 'u2', 'u3']
2. Spezifischer Qubit-Quantenfehler
Damit wird der Fehler auf jedes Vorkommen eines Befehls angewendet, der auf eine bestimmte Liste von Qubits wirkt. Man beachte, dass die Reihenfolge der Qubits eine Rolle spielt: Ein Fehler, der bei einem Zwei-Qubit-Tor auf die Qubits [0 und 1] angewendet wird, ist anders als ein Fehler, der auf die Qubits [1 und 0] angewendet wird.
Sie wird als noise_model.add_quantum_error(error, instructions, qubits) hinzugefügt:
# 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)Output:
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
Instructions with noise: ['u2', 'u3', 'u1']
Qubits with noise: [0]
Specific qubit errors: [('u1', (0,)), ('u2', (0,)), ('u3', (0,))]
Hinweis zu nicht-lokalen Qubit-Quantenfehlern
NoiseModel unterstützt keine Hinzufügung von nicht-lokalen Quantenfehlern bei Qubits. Sie sollten außerhalb von NoiseModel. behandelt werden. Das bedeutet, dass Sie Ihren eigenen Transpiler-Pass (TransformationPass) schreiben und diesen unmittelbar vor dem Start des Simulators ausführen sollten, wenn Sie Ihre Quantenfehler unter Ihren eigenen Bedingungen in Ihre Schaltung einfügen möchten.
Führen Sie eine Geräuschsimulation mit einem Geräuschmodell durch
Der Befehl AerSimulator(noise_model=noise_model) gibt einen für das angegebene Rauschmodell konfigurierten Simulator zurück. Neben der Einstellung des Rauschmodells des Simulators werden auch die Basis-Gates des Simulators entsprechend den Gates des Rauschmodells überschrieben.
Beispiele für Geräuschmodelle
Wir werden nun einige Beispiele für Rauschmodelle geben. Für unsere Demonstrationen verwenden wir eine einfache Testschaltung, die einen n-Qubit-GHZ-Zustand erzeugt:
# 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)Output:
┌───┐ ░ ┌─┐
q_0: ┤ H ├──■─────────────░─┤M├─────────
└───┘┌─┴─┐ ░ └╥┘┌─┐
q_1: ─────┤ X ├──■────────░──╫─┤M├──────
└───┘┌─┴─┐ ░ ║ └╥┘┌─┐
q_2: ──────────┤ X ├──■───░──╫──╫─┤M├───
└───┘┌─┴─┐ ░ ║ ║ └╥┘┌─┐
q_3: ───────────────┤ X ├─░──╫──╫──╫─┤M├
└───┘ ░ ║ ║ ║ └╥┘
meas: 4/════════════════════════╩══╩══╩══╩═
0 1 2 3
Ideale Simulation
# Ideal simulator and execution
sim_ideal = AerSimulator()
result_ideal = sim_ideal.run(circ).result()
plot_histogram(result_ideal.get_counts(0))Output:
Rauschbeispiel 1: Einfaches Bit-Flip-Fehler-Rauschmodell
Betrachten wir ein einfaches Beispiel für ein Spielzeug-Rauschmodell, das in der Forschung zur Quanteninformationstheorie üblich ist:
- Bei der Anwendung eines Ein-Qubit-Gatters wird der Zustand des Qubits mit der Wahrscheinlichkeit
p_gate1umgedreht. - Bei der Anwendung eines Zwei-Qubit-Gatters sind auf jedes Qubit Einzel-Qubit-Fehler anzuwenden.
- Beim Zurücksetzen eines Qubits wird es mit der Wahrscheinlichkeit
p_resetauf 1 statt auf 0 zurückgesetzt. - Bei der Messung eines Qubits wird der Zustand des Qubits mit der Wahrscheinlichkeit
p_measumgedreht.
# 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)Output:
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']
Instructions with noise: ['u2', 'u1', 'reset', 'cx', 'measure', 'u3']
All-qubits errors: ['reset', 'measure', 'u1', 'u2', 'u3', 'cx']
Führen Sie die laute Simulation aus
# 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)Output:
Beispiel 2: Thermische Relaxation von T1/T2
Betrachten wir nun ein realistischeres Fehlermodell, das auf thermischer Relaxation mit der Qubit-Umgebung beruht:
- Jedes Qubit ist durch eine thermische Relaxationszeitkonstante und eine Dephasierungszeitkonstante parametrisiert.
- Beachten Sie, dass wir haben müssen.
- Die Fehlerquoten bei Befehlen werden durch die Gatterzeiten und die Qubit-Werte , bestimmt.
# 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)Output:
NoiseModel:
Basis gates: ['cx', 'id', 'rz', 'sx', 'u2', 'u3']
Instructions with noise: ['u2', 'reset', 'cx', 'measure', 'u3']
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))]
Führen Sie die laute Simulation aus
# 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)Output:
Nächste Schritte
- Informationen zur Simulation von Schaltungen mit Rauschen finden Sie unter „Exakte und rauschbehaftete Simulation mit Qiskit Aer-Primitiven “.
- Lesen Sie die Referenz des Qiskit Aer noise module.