סימולציה מדויקת ורועשת עם 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")
מעגל זה מכיל פרמטרים לייצוג זוויות הסיבוב עבור Gate ו-. בעת סימולציה של מעגל זה, עלינו לציין ערכים מפורשים לפרמטרים אלו. בתא הבא, נציין כמה ערכים לפרמטרים אלו ונשתמש ב-Estimator primitive מ-Qiskit Aer לחישוב ערך התוחלת המדויק של האובסרבל .
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 עם הסתברות מוגדרת כערוץ קוונטי שפועל באופן הבא על מטריצת צפיפות :
כאשר הוא מספר ה-Qubit, במקרה זה, 2. כלומר, עם הסתברות , המצב מוחלף במצב המעורב לחלוטין, והמצב נשמר עם הסתברות . לאחר יישומים של ערוץ ה-depolarizing, ההסתברות שהמצב נשמר תהיה . לכן, אנחנו מצפים שההסתברות לשמירת המצב הנכון בסוף הסימולציה תרד באופן מעריכי עם מספר ה-Gateים מסוג CX במעגל שלנו.
בואו נספור את מספר ה-Gateים מסוג CX במעגל שלנו ונחשב . נקרא ל-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}
צעדים הבאים
- לסימולציה של מעגלים קטנים ופשוטים, ראה סימולציה מדויקת עם Qiskit SDK primitives.
- ראה בתיעוד Qiskit Aer.