Quantum noise and error mitigation
Toshinari Itoko (28 יוני 2024)
הורד את קובץ ה-PDF של ההרצאה המקורית. שים לב שחלק מקטעי הקוד עשויים להיות מיושנים מכיוון שאלה תמונות סטטיות.
זמן QPU משוער להרצת הניסוי הזה הוא 1 דקה ו-40 שניות.
1. מבוא
לאורך השיעור הזה נבחן רעש וכיצד ניתן להפחית אותו במחשבים קוונטיים. נתחיל בבחינת השפעות הרעש באמצעות סימולטור שיכול לדמות רעש בכמה דרכים, כולל שימוש בפרופילי רעש ממחשבים קוונטיים אמיתיים. לאחר מכן נעבור למחשבים קוונטיים אמיתיים, שבהם הרעש הוא מובנה. נבחן את השפעות הפחתת השגיאות, כולל שילובים של דברים כמו אקסטרפולציית אפס-רעש (ZNE) וסיבוב Gate.
נתחיל בטעינת כמה חבילות.
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib qiskit qiskit-aer qiskit-ibm-runtime
# !pip install qiskit qiskit_aer qiskit_ibm_runtime
# !pip install jupyter
# !pip install matplotlib pylatexenc
import qiskit
qiskit.__version__
'2.0.2'
import qiskit_aer
qiskit_aer.__version__
'0.17.1'
import qiskit_ibm_runtime
qiskit_ibm_runtime.__version__
'0.40.1'
2. סימולציה רועשת ללא הפחתת שגיאות
Qiskit Aer הוא סימולטור קלאסי לחישוב קוונטי. הוא יכול לדמות לא רק הרצה אידיאלית אלא גם הרצה רועשת של Circuit קוונטי. מחברת זו ממחישה כיצד להריץ סימולציה רועשת באמצעות Qiskit Aer:
- בנה מודל רעש
- בנה Sampler רועש (סימולטור) עם מודל הרעש
- הרץ Circuit קוונטי על ה-Sampler הרועש
noise_model = NoiseModel()
...
noisy_sampler = Sampler(options={"backend_options": {"noise_model": noise_model}})
job = noisy_sampler.run([circuit])
2.1 בנה Circuit בדיקה
אנחנו בוחנים Circuit של Qubit בודד לצורך משחק שפשוט חוזר על Gate ה-X d פעמים (d=0 ... 100) ומודד את הנצפה Z.
from qiskit.circuit import QuantumCircuit
MAX_DEPTH = 100
circuits = []
for d in range(MAX_DEPTH + 1):
circ = QuantumCircuit(1)
for _ in range(d):
circ.x(0)
circ.barrier(0)
circ.measure_all()
circuits.append(circ)
display(circuits[3].draw(output="mpl"))
from qiskit.quantum_info import SparsePauliOp
obs = SparsePauliOp.from_list([("Z", 1.0)])
obs
SparsePauliOp(['Z'],
coeffs=[1.+0.j])
2.2 בנה מודל רעש
כדי לבצע סימולציה רועשת, אנחנו צריכים לציין NoiseModel. נראה כיצד לבנות NoiseModel בסעיף זה.
קודם כל צריך להגדיר שגיאות קוונטיות (או שגיאות קריאה) להוספה למודל הרעש.
from qiskit_aer.noise.errors import (
coherent_unitary_error,
amplitude_damping_error,
ReadoutError,
)
from qiskit.circuit.library import RXGate
# Coherent (unitary) error: Over X-rotation error
# https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.noise.coherent_unitary_error.html#qiskit_aer.noise.coherent_unitary_error
OVER_ROTATION_ANGLE = 0.05
coherent_error = coherent_unitary_error(RXGate(OVER_ROTATION_ANGLE).to_matrix())
# Incoherent error: Amplitude dumping error
# https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.noise.amplitude_damping_error.html#qiskit_aer.noise.amplitude_damping_error
AMPLITUDE_DAMPING_PARAM = 0.02 # in [0, 1] (0: no error)
incoherent_error = amplitude_damping_error(AMPLITUDE_DAMPING_PARAM)
# Readout (measurement) error: Readout error
# https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.noise.ReadoutError.html#qiskit_aer.noise.ReadoutError
PREP0_MEAS1 = 0.03 # P(1|0): Probability of preparing 0 and measuring 1
PREP1_MEAS0 = 0.08 # P(0|1): Probability of preparing 1 and measuring 0
readout_error = ReadoutError(
[[1 - PREP0_MEAS1, PREP0_MEAS1], [PREP1_MEAS0, 1 - PREP1_MEAS0]]
)
from qiskit_aer.noise import NoiseModel
noise_model = NoiseModel()
noise_model.add_quantum_error(coherent_error.compose(incoherent_error), "x", (0,))
noise_model.add_readout_error(readout_error, (0,))
2.3 בנה Sampler רועש עם מודל הרעש
from qiskit_aer.primitives import SamplerV2 as Sampler
noisy_sampler = Sampler(options={"backend_options": {"noise_model": noise_model}})
2.4 הרץ Circuit קוונטי על ה-Sampler הרועש
job = noisy_sampler.run(circuits, shots=400)
result = job.result()
result[0].data.meas.get_counts()
{'0': 389, '1': 11}
2.5 הצג תוצאות
import matplotlib.pyplot as plt
plt.title("Noisy simulation")
ds = list(range(MAX_DEPTH + 1))
plt.plot(
ds,
[result[d].data.meas.expectation_values(["Z"]) for d in ds],
color="gray",
linestyle="-",
)
plt.scatter(ds, [result[d].data.meas.expectation_values(["Z"]) for d in ds], marker="o")
plt.hlines(0, xmin=0, xmax=MAX_DEPTH, colors="black")
plt.ylim(-1, 1)
plt.xlabel("Circuit depth")
plt.ylabel("Measured <Z>")
plt.show()
2.6 סימולציה אידיאלית
ideal_sampler = Sampler()
job_ideal = ideal_sampler.run(circuits)
result_ideal = job_ideal.result()
plt.title("Ideal simulation")
ds = list(range(MAX_DEPTH + 1))
plt.plot(
ds,
[result_ideal[d].data.meas.expectation_values(["Z"]) for d in ds],
color="gray",
linestyle="-",
)
plt.scatter(
ds, [result_ideal[d].data.meas.expectation_values(["Z"]) for d in ds], marker="o"
)
plt.hlines(0, xmin=0, xmax=MAX_DEPTH, colors="black")
plt.xlabel("Circuit depth")
plt.ylabel("Measured <Z>")
plt.show()

2.7 תרגיל
על ידי שינוי הקוד להלן,
- נסה 25 פעמים יותר shots (= 10_000 shots) וודא שמתקבל גרף חלק יותר
- שנה פרמטרי רעש (OVER_ROTATION_ANGLE, AMPLITUDE_DAMPING_PARAM, PREP0_MEAS1, או PREP1_MEAS0) וראה כיצד הגרף משתנה
OVER_ROTATION_ANGLE = 0.05
coherent_error = coherent_unitary_error(RXGate(OVER_ROTATION_ANGLE).to_matrix())
AMPLITUDE_DAMPING_PARAM = 0.02 # in [0, 1] (0: no error)
incoherent_error = amplitude_damping_error(AMPLITUDE_DAMPING_PARAM)
PREP0_MEAS1 = 0.1 # P(1|0): Probability of preparing 0 and measuring 1
PREP1_MEAS0 = 0.05 # P(0|1): Probability of preparing 1 and measuring 0
readout_error = ReadoutError(
[[1 - PREP0_MEAS1, PREP0_MEAS1], [PREP1_MEAS0, 1 - PREP1_MEAS0]]
)
noise_model = NoiseModel()
noise_model.add_quantum_error(coherent_error.compose(incoherent_error), "x", (0,))
noise_model.add_readout_error(readout_error, (0,))
options = {
"backend_options": {"noise_model": noise_model},
}
noisy_sampler = Sampler(options=options)
job = noisy_sampler.run(circuits, shots=400)
result = job.result()
plt.title("Noisy simulation")
ds = list(range(MAX_DEPTH + 1))
plt.plot(
ds,
[result[d].data.meas.expectation_values(["Z"]) for d in ds],
marker="o",
linestyle="-",
)
plt.hlines(0, xmin=0, xmax=MAX_DEPTH, colors="black")
plt.ylim(-1, 1)
plt.xlabel("Depth")
plt.ylabel("Measured <Z>")
plt.show()
2.8 סימולציה רועשת ריאליסטית יותר
from qiskit_aer import AerSimulator
from qiskit_ibm_runtime import SamplerV2 as Sampler, QiskitRuntimeService
service = QiskitRuntimeService()
real_backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
) # Eagle
<IBMBackend('ibm_strasbourg')>
aer = AerSimulator.from_backend(real_backend)
noisy_sampler = Sampler(mode=aer)
job = noisy_sampler.run(circuits)
result = job.result()
plt.title("Noisy simulation with noise model from real backend")
ds = list(range(MAX_DEPTH + 1))
plt.plot(
ds,
[result[d].data.meas.expectation_values(["Z"]) for d in ds],
marker="o",
linestyle="-",
)
plt.hlines(0, xmin=0, xmax=MAX_DEPTH, colors="black")
plt.ylim(-1, 1)
plt.xlabel("Depth")
plt.ylabel("Measured <Z>")
plt.show()
