דלג לתוכן הראשי
פרויקט זה בשלב בטא. מצאת באג? פתח issue ב-GitHub. יש שאלה או רעיון? שאל ב-Discussions — נשמח לשמוע ממך!
מה איכות התרגום בדף זה?

בנה מודלי רעש

גרסאות חבילות

הקוד בדף זה פותח בשימוש בדרישות הבאות. אנחנו ממליצים להשתמש בגרסאות אלה או בגרסאות חדשות יותר.

qiskit[all]~=2.5.2
qiskit-ibm-runtime~=0.47.0
qiskit-aer~=0.17

דף זה מדגים כיצד להשתמש במודול noise של Qiskit Aer לבניית מודלי רעש לסימולציה של מעגלים קוונטיים בנוכחות שגיאות. זה שימושי לאמולציה של מעבדים קוונטיים רועשים ולחקר השפעות הרעש על ביצוע אלגוריתמים קוונטיים.

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "qiskit": "qiskit", "qiskit_aer": "qiskit-aer", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
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,
)

מודול noise של Qiskit Aer​

מודול noise של Qiskit Aer מכיל מחלקות Python לבניית מודלי רעש מותאמים אישית לסימולציה. ישנן שלוש מחלקות מפתח:

  1. המחלקה NoiseModel המאחסנת מודל רעש המשמש לסימולציה רועשת.

  2. המחלקה QuantumError המתארת שגיאות Gate מסוג CPTP. ניתן להחיל אותן:

    • אחרי הוראות gate או reset

    • לפני הוראות measure.

  3. המחלקה ReadoutError המתארת שגיאות קריאה קלאסיות.

אתחול מודל רעש מ-Backend​

ניתן לאתחל מודל רעש עם פרמטרים שנקבעו מנתוני הכיול העדכניים של Backend פיזי.

הערה

ה-Backend המדומה FakeSherbrooke מ-qiskit_ibm_runtime משמש בדוגמאות אלה, אך ניתן לנסות זאת על כל Backend אמיתי או מדומה תואם Qiskit.

from qiskit_ibm_runtime.fake_provider import FakeSherbrooke

backend = FakeSherbrooke()
noise_model = NoiseModel.from_backend(backend)

פעולה זו תניב מודל רעש שמקרב באופן גס את השגיאות שתיתקל בהן בשימוש ב-Backend הזה. אם ברצונך לשלוט בצורה מדויקת יותר בפרמטרים של מודל הרעש, תצטרך ליצור מודל רעש משלך, כפי שמתואר בהמשך דף זה.

שגיאות קוונטיות​

במקום לעבוד ישירות עם אובייקט QuantumError, קיימות פונקציות עזר רבות שמייצרות אוטומטית סוג ספציפי של שגיאה קוונטית פרמטרית. פונקציות אלה נמצאות במודול noise וכוללות פונקציות עבור סוגי שגיאות נפוצים רבים בחקר המחשוב הקוונטי. שמות הפונקציות וסוג השגיאה שהן מחזירות:

פונקציית שגיאה סטנדרטיתפרטים
kraus_errorערוץ שגיאה כללי CPTP עבור n-Qubit, נתון כרשימת מטריצות Kraus [K0,...][K_0, ...].
mixed_unitary_errorשגיאה יוניטרית מעורבת עבור n-Qubit, נתונה כרשימת מטריצות יוניטריות והסתברויות [(U0,p0),...][(U_0, p_0),...].
coherent_unitary_errorשגיאה יוניטרית קוהרנטית עבור n-Qubit, נתונה כמטריצה יוניטרית בודדת UU.
pauli_errorערוץ שגיאת Pauli עבור n-Qubit (יוניטרי מעורב), נתון כרשימת אופרטורי Pauli והסתברויות [(P0,p0),...][(P_0, p_0),...]
depolarizing_errorערוץ שגיאת depolarizing עבור n-Qubit, מאופיין על ידי הסתברות depolarization pp.
reset_errorשגיאת reset עבור qubit יחיד, מאופיינת על ידי הסתברויות p0,p1p_0, p_1 של איפוס למצב ∣0⟩\vert0\rangle, ∣1⟩\vert1\rangle.
thermal_relaxation_errorערוץ רלקסציה תרמית עבור qubit יחיד, מאופיין על ידי קבועי זמן רלקסציה T1T_1, T2T_2, זמן Gate tt, ואכלוס תרמי של המצב המעורר p1p_1.
phase_amplitude_damping_errorערוץ שגיאת דעיכה כללי ומשולב של פאזה ואמפליטודה עבור qubit יחיד, נתון על ידי פרמטר דעיכת אמפליטודה λ\lambda, פרמטר דעיכת פאזה γ\gamma, ואכלוס תרמי של המצב המעורר p1p_1.
amplitude_damping_errorערוץ שגיאת דעיכת אמפליטודה כללי עבור qubit יחיד, נתון על ידי פרמטר דעיכת אמפליטודה λ\lambda, ואכלוס תרמי של המצב המעורר p1p_1.
phase_damping_errorערוץ שגיאת דעיכת פאזה עבור qubit יחיד, נתון על ידי פרמטר דעיכת פאזה γ\gamma.

שילוב שגיאות קוונטיות​

ניתן לשלב מופעי QuantumError באמצעות קומפוזיציה, מכפלת טנזור, והרחבת טנזור (מכפלת טנזור בסדר הפוך) ליצירת QuantumErrors חדשים כדלקמן:

  • קומפוזיציה: E(ρ)=E2(E1(ρ))\cal{E}(\rho)=\cal{E_2}(\cal{E_1}(\rho)) כ-error = error1.compose(error2)

  • מכפלת טנזור: E(ρ)=(E1⊗E2)(ρ)\cal{E}(\rho) =(\cal{E_1}\otimes\cal{E_2})(\rho) כ-error = error1.tensor(error2)

  • מכפלת הרחבה: E(ρ)=(E2⊗E1)(ρ)\cal{E}(\rho) =(\cal{E_2}\otimes\cal{E_1})(\rho) כ-error = error1.expand(error2)

דוגמה​

כדי לבנות שגיאת היפוך-ביט של 5% עבור 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 ├
└───┘

המרה אל אופרטורי QuantumChannel וממנם​

ניתן גם להמיר בין אובייקטי QuantumError ב-Qiskit Aer לבין אובייקטי QuantumChannel ב-Qiskit ולהפך.

# Convert to Kraus operator
bit_flip_kraus = Kraus(bit_flip)
print(bit_flip_kraus)
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)
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

שגיאת קריאה​

שגיאות קריאה קלאסיות מוגדרות על ידי רשימת וקטורי הסתברות הקצאה P(A∣B)P(A|B):

  • AA הוא ערך הביט הקלאסי המתועד

  • BB הוא ערך הביט האמיתי המוחזר מהמדידה

לדוגמה, עבור qubit אחד: P(A∣B)=[P(A∣0),P(A∣1)] P(A|B) = [P(A|0), P(A|1)].

# 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 ]])

ניתן גם לשלב שגיאות קריאה באמצעות compose, tensor ו-expand, בדומה לשגיאות קוונטיות.

הוספת שגיאות למודל רעש​

בעת הוספת שגיאה קוונטית למודל רעש, עליך לציין את סוג ההוראה שעליה היא פועלת ואילו qubits להחיל אותה עליהם. ישנם שני סוגים של שגיאות קוונטיות:

  1. שגיאה קוונטית לכל ה-Qubits

  2. שגיאה קוונטית ל-Qubit ספציפי

1. שגיאה קוונטית לכל ה-Qubits​

פעולה זו מחילה את אותה שגיאה על כל מופע של הוראה, ללא קשר לאילו qubits היא פועלת.

מוסיפים אותה כ-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: ['u2', 'u3', 'u1']
All-qubits errors: ['u1', 'u2', 'u3']

2. שגיאה קוונטית ל-Qubit ספציפי​

פעולה זו מחילה את השגיאה על כל מופע של הוראה הפועלת על רשימת qubits מוגדרת. שים לב שסדר ה-Qubits חשוב: לדוגמה, שגיאה המוחלת על qubits [0, 1] עבור Gate דו-Qubit שונה מזו המוחלת על qubits [1, 0].

מוסיפים אותה כ-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: ['u2', 'u3', 'u1']
Qubits with noise: [0]
Specific qubit errors: [('u1', (0,)), ('u2', (0,)), ('u3', (0,))]

הערה על שגיאות קוונטיות לא-מקומיות​

NoiseModel אינו תומך בהוספת שגיאות קוונטיות לא-מקומיות. יש לטפל בהן מחוץ ל-NoiseModel. לכן, אם ברצונך להוסיף שגיאות קוונטיות למעגל בתנאים משלך, מומלץ לכתוב מעבר Transpiler משלך (TransformationPass) ולהריץ אותו ממש לפני הרצת הסימולטור.

הרצת סימולציה רועשת עם מודל רעש​

הפקודה AerSimulator(noise_model=noise_model) מחזירה סימולטור שמוגדר למודל הרעש הנתון. בנוסף להגדרת מודל הרעש של הסימולטור, היא גם דורסת את ה-Gates הבסיסיים של הסימולטור, בהתאם ל-Gates של מודל הרעש.

דוגמאות למודל רעש​

כעת נציג כמה דוגמאות למודלי רעש. לצורך ההדגמות שלנו אנחנו משתמשים ב-Circuit בדיקה פשוט המייצר מצב GHZ בן n-Qubit:

# 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

סימולציה אידיאלית​

# Ideal simulator and execution
sim_ideal = AerSimulator()
result_ideal = sim_ideal.run(circ).result()
plot_histogram(result_ideal.get_counts(0))

Output of the previous code cell

דוגמת רעש 1: מודל רעש פשוט של שגיאת היפוך-ביט​

נשקול דוגמת צעצוע פשוטה של מודל רעש, נפוצה בחקר תורת המידע הקוונטי:

  • בעת הפעלת Gate חד-Qubit, הפוך את מצב ה-Qubit בהסתברות p_gate1.

  • בעת הפעלת Gate דו-Qubit, החל שגיאות חד-Qubit על כל qubit.

  • בעת איפוס qubit, אפס ל-1 במקום 0 בהסתברות p_reset.

  • בעת מדידת qubit, הפוך את מצב ה-Qubit בהסתברות 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: ['u2', 'u1', 'reset', 'cx', 'measure', 'u3']
All-qubits errors: ['reset', 'measure', 'u1', 'u2', 'u3', 'cx']

הרצת הסימולציה הרועשת​

# 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 of the previous code cell

דוגמה 2: רלקסציה תרמית T1/T2​

כעת נשקול מודל שגיאות ריאליסטי יותר המבוסס על רלקסציה תרמית עם סביבת ה-Qubit:

  • כל qubit מאופיין על ידי קבוע זמן רלקסציה תרמית T1T_1 וקבוע זמן dephasing T2T_2.
  • שים לב שחייב להתקיים T2≤2T1T_2 \le 2 T_1.
  • שיעורי שגיאות בהוראות נקבעים על ידי זמני Gate וערכי T1T_1, T2T_2 של ה-Qubit.
# 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: ['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))]

הרצת הסימולציה הרועשת​

# 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 of the previous code cell

צעדים הבאים​

המלצות