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

סימולציה מדויקת ורועשת עם Qiskit Aer primitives

Package versions

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

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

סימולציה מדויקת עם Qiskit SDK primitives מדגים כיצד להשתמש ב-primitives הייחוסיים הכלולים ב-Qiskit לביצוע סימולציה מדויקת של מעגלים קוונטיים. מעבדים קוונטיים הקיימים כיום סובלים משגיאות, או רעש, ולכן תוצאות סימולציה מדויקת אינן משקפות בהכרח את התוצאות שהיית מצפה להן בעת הרצת מעגלים על חומרה אמיתית. בעוד ש-primitives הייחוסיים ב-Qiskit אינם תומכים במידול רעש, Qiskit Aer כולל מימושים של ה-primitives שכן תומכים במידול רעש. Qiskit Aer הוא סימולטור מעגלים קוונטיים בעל ביצועים גבוהים שניתן להשתמש בו במקום ה-primitives הייחוסיים לביצועים טובים יותר ותכונות נוספות. הוא חלק מ-Qiskit Ecosystem. במאמר זה, נדגים את השימוש ב-Qiskit Aer primitives לסימולציה מדויקת ורועשת.

הערות
  • נדרש qiskit-aer גרסה 0.14 ומעלה.
  • בעוד ש-Qiskit Aer primitives מממשים את ממשקי ה-primitive, הם אינם מספקים את אותן האפשרויות כמו IBM Quantum primitives. רמת חוסן (Resilience level), לדוגמה, אינה זמינה עם Qiskit Aer primitives.
  • ראה את תיעוד AerSimulator לפרטים על אפשרויות שיטת הסימולציה ש-Aer תומך בהן.

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

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

_needed = {"qiskit": "qiskit", "qiskit_aer": "qiskit-aer"}
_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")
from qiskit.circuit.library import efficient_su2

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

Output of the previous code cell

מעגל זה מכיל פרמטרים לייצוג זוויות הסיבוב עבור Gate RyR_y ו-RzR_z. בעת סימולציה של מעגל זה, עלינו לציין ערכים מפורשים לפרמטרים אלו. בתא הבא, נציין כמה ערכים לפרמטרים אלו ונשתמש ב-Estimator primitive מ-Qiskit Aer לחישוב ערך התוחלת המדויק של האובסרבל ZZ⋯ZZZ \cdots Z.

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

כעת, נאתחל מודל רעש הכולל שגיאת depolarizing של 2% על כל Gate CX. בפועל, השגיאה הנובעת מ-Gateים דו-קיוביטיים (כאן, Gateים מסוג CX) היא המקור הדומיננטי לשגיאה בעת הרצת מעגל. ראה בניית מודלי רעש לסקירה של בניית מודלי רעש ב-Qiskit Aer.

בתא הבא, נבנה Estimator המשלב מודל רעש זה ונשתמש בו לחישוב ערך התוחלת של האובסרבל.

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.7247404214143529

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

כדי לקבל מושג גס מאוד כיצד הרעש משפיע על התוצאה הסופית, התבונן במודל הרעש שלנו, המוסיף שגיאת depolarizing של 2% לכל Gate CX. שגיאת depolarizing עם הסתברות pp מוגדרת כערוץ קוונטי EE שפועל באופן הבא על מטריצת צפיפות ρ\rho:

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

כאשר nn הוא מספר ה-Qubit, במקרה זה, 2. כלומר, עם הסתברות pp, המצב מוחלף במצב המעורב לחלוטין, והמצב נשמר עם הסתברות 1−p1 - p. לאחר mm יישומים של ערוץ ה-depolarizing, ההסתברות שהמצב נשמר תהיה (1−p)m(1 - p)^m. לכן, אנחנו מצפים שההסתברות לשמירת המצב הנכון בסוף הסימולציה תרד באופן מעריכי עם מספר ה-Gateים מסוג CX במעגל שלנו.

בואו נספור את מספר ה-Gateים מסוג CX במעגל שלנו ונחשב (1−p)m(1 - p)^m. נקרא ל-count_ops כדי לקבל מילון שממפה שמות של Gateים למספר המופעים שלהם, ונאחזר את הערך עבור Gate CX.

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

ערך זה, 65%, נותן אומדן גס של ההסתברות שהמצב הסופי שלנו נכון. זהו אומדן שמרני מכיוון שאינו לוקח בחשבון את המצב ההתחלתי של הסימולציה.

תא הקוד הבא מציג כיצד להשתמש ב-Sampler primitive מ-Qiskit Aer לדגימה מהמעגל הרועש. עלינו להוסיף מדידות למעגל לפני הרצתו עם ה-Sampler primitive.

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()
{'00000000': 69,
'00100000': 2,
'00000110': 1,
'11000000': 2,
'00010100': 1,
'01100000': 2,
'01010000': 3,
'00101000': 1,
'10100000': 2,
'01100101': 1,
'00001010': 1,
'10000000': 2,
'00000010': 3,
'01000000': 4,
'11100000': 1,
'10000101': 1,
'00110000': 1,
'00001100': 1,
'00011000': 2}

צעדים הבאים​

המלצות