Zum Hauptinhalt springen

Exakte und verrauschte Simulation mit Qiskit Aer Primitiven

Paketversionen

Der Code auf dieser Seite wurde mit den folgenden Anforderungen entwickelt. Wir empfehlen, diese oder neuere Versionen zu verwenden.

qiskit[all]~=2.3.0
qiskit-aer~=0.17

Exakte Simulation mit Qiskit Primitiven zeigt, wie du die in Qiskit enthaltenen Referenz-Primitive verwendest, um Quantum Circuits exakt zu simulieren. Derzeit existierende Quantenprozessoren leiden unter Fehlern, sogenanntem Rauschen (Noise), sodass die Ergebnisse einer exakten Simulation nicht unbedingt den Ergebnissen entsprechen, die du beim Ausführen von Circuits auf echter Hardware erwarten würdest. Während die Referenz-Primitive in Qiskit keine Modellierung von Rauschen unterstützen, enthält Qiskit Aer Implementierungen der Primitive, die dies unterstützen. Qiskit Aer ist ein hochperformanter Quantum Circuit Simulator, den du anstelle der Referenz-Primitive für bessere Leistung und mehr Funktionen einsetzen kannst. Es ist Teil des Qiskit Ecosystem. In diesem Artikel zeigen wir die Verwendung von Qiskit Aer Primitiven für die exakte und verrauschte Simulation.

Hinweise
  • qiskit-aer v0.14 oder neuer ist erforderlich.
  • Obwohl die Qiskit Aer Primitive die Primitive-Schnittstellen implementieren, bieten sie nicht dieselben Optionen wie die Qiskit Runtime Primitive. Resilience Level ist beispielsweise bei Qiskit Aer Primitiven nicht verfügbar.
  • Weitere Informationen zu den von Aer unterstützten Simulationsmethoden findest du in der AerSimulator-Dokumentation.

Um die exakte und verrauschte Simulation zu erkunden, erstelle einen Beispiel-Circuit mit acht Qubits:

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-aer
from qiskit.circuit.library import efficient_su2

n_qubits = 8
circuit = efficient_su2(n_qubits)
circuit.draw("mpl")

Ausgabe der vorherigen Code-Zelle

Dieser Circuit enthält Parameter, die die Rotationswinkel für RyR_y- und RzR_z-Gates darstellen. Bei der Simulation dieses Circuits müssen wir explizite Werte für diese Parameter angeben. In der nächsten Zelle legen wir einige Werte für diese Parameter fest und verwenden den Estimator Primitive von Qiskit Aer, um den exakten Erwartungswert des Observablen ZZZZZ \cdots Z zu berechnen.

from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_aer import AerSimulator
from qiskit_aer.primitives import EstimatorV2 as Estimator

observable = SparsePauliOp("Z" * n_qubits)
params = [0.1] * circuit.num_parameters

exact_estimator = Estimator()
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(circuit)
pub = (isa_circuit, observable, params)
job = exact_estimator.run([pub])
result = job.result()
pub_result = result[0]
exact_value = float(pub_result.data.evs)
exact_value
0.8870140234256602

Nun initialisieren wir ein Rauschmodell, das einen Depolarisierungsfehler von 2 % auf jedem CX-Gate enthält. In der Praxis sind die Fehler, die durch die Zwei-Qubit-Gates entstehen – hier CX-Gates –, die dominierende Fehlerquelle beim Ausführen eines Circuits. Einen Überblick über die Konstruktion von Rauschmodellen in Qiskit Aer findest du unter Rauschmodelle erstellen.

In der nächsten Zelle erstellen wir einen Estimator, der dieses Rauschmodell einbezieht, und verwenden ihn zur Berechnung des Erwartungswerts des Observablen.

from qiskit_aer.noise import NoiseModel, depolarizing_error

noise_model = NoiseModel()
cx_depolarizing_prob = 0.02
noise_model.add_all_qubit_quantum_error(
depolarizing_error(cx_depolarizing_prob, 2), ["cx"]
)

noisy_estimator = Estimator(
options=dict(backend_options=dict(noise_model=noise_model))
)
job = noisy_estimator.run([pub])
result = job.result()
pub_result = result[0]
noisy_value = float(pub_result.data.evs)
noisy_value
0.7247404214143528

Wie du siehst, weicht der Erwartungswert in Gegenwart des Rauschens erheblich vom korrekten Wert ab. In der Praxis gibt es verschiedene Fehlerminderungstechniken, um die Auswirkungen des Rauschens zu bekämpfen, jedoch würde eine Diskussion dieser Techniken den Rahmen dieses Artikels sprengen.

Um ein grobes Gefühl dafür zu bekommen, wie das Rauschen das Endergebnis beeinflusst, betrachte unser Rauschmodell, das jedem CX-Gate einen Depolarisierungsfehler von 2 % hinzufügt. Ein Depolarisierungsfehler mit Wahrscheinlichkeit pp ist als Quantenkanal EE definiert, der die folgende Wirkung auf eine Dichtematrix ρ\rho hat:

E(ρ)=(1p)ρ+pI2nE(\rho) = (1 - p) \rho + p\frac{I}{2^n}

wobei nn die Anzahl der Qubits ist, in diesem Fall 2. Das heißt, mit Wahrscheinlichkeit pp wird der Zustand durch den vollständig gemischten Zustand ersetzt, und mit Wahrscheinlichkeit 1p1 - p bleibt der Zustand erhalten. Nach mm Anwendungen des Depolarisierungskanals beträgt die Wahrscheinlichkeit, dass der Zustand erhalten bleibt, (1p)m(1 - p)^m. Daher erwarten wir, dass die Wahrscheinlichkeit, am Ende der Simulation den korrekten Zustand zu behalten, mit der Anzahl der CX-Gates in unserem Circuit exponentiell abnimmt.

Zählen wir die Anzahl der CX-Gates in unserem Circuit und berechnen (1p)m(1 - p)^m. Wir rufen count_ops auf, um ein Dictionary zu erhalten, das Gate-Namen auf ihre Anzahl abbildet, und lesen den Eintrag für das CX-Gate aus.

cx_count = circuit.count_ops()["cx"]
(1 - cx_depolarizing_prob) ** cx_count
0.6542558123199923

Dieser Wert, 65 %, gibt eine grobe Schätzung der Wahrscheinlichkeit, dass unser Endzustand korrekt ist. Es ist eine konservative Schätzung, da sie den Anfangszustand der Simulation nicht berücksichtigt.

Die folgende Code-Zelle zeigt, wie du den Sampler Primitive von Qiskit Aer verwendest, um aus dem verrauschten Circuit zu sampeln. Wir müssen dem Circuit Messungen hinzufügen, bevor wir ihn mit dem Sampler Primitive ausführen.

from qiskit_aer.primitives import SamplerV2 as Sampler

measured_circuit = circuit.copy()
measured_circuit.measure_all()

noisy_sampler = Sampler(
options=dict(backend_options=dict(noise_model=noise_model))
)
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(measured_circuit)
pub = (isa_circuit, params, 100)
job = noisy_sampler.run([pub])
result = job.result()
pub_result = result[0]
pub_result.data.meas.get_counts()
{'00100000': 1,
'00000000': 65,
'10101000': 1,
'10000000': 5,
'00001000': 1,
'00000110': 2,
'11110010': 1,
'00000011': 3,
'01010000': 3,
'11000000': 3,
'01111000': 1,
'01000000': 2,
'00000010': 1,
'01100000': 1,
'00011000': 1,
'00111100': 1,
'00010100': 1,
'00001111': 1,
'00110000': 1,
'01100101': 1,
'00000100': 1,
'10100000': 1,
'00000001': 1,
'11010000': 1}

Nächste Schritte

Empfehlungen