פרוס והרץ תבנית פונקציית Qiskit עבור דינמיקת המילטוניאן AQC + Trotter
סקירה כללית
זוהי תבנית פונקציית Qiskit שאינה תלוית ניסוי עבור דינמיקת המילטוניאן. בהינתן המילטוניאן פאולי חד-ממדי עם שכנים קרובים, מצב התחלתי מוכן (אופציונלי), וסט של תצפיות, היא מריצה אבולוציית זמן Trotter, כיווץ מעגל של קימפול קוונטי מקורב (AQC), והרצה מוקהה, ואז מחזירה את סדרת הזמן של כל תצפית. החלף את ההגדרה (PRE) ואת הניתוח (POST) — ואותה ליבה עצמה תניע ניסוי אחר:
| PRE (ההגדרה שלך) | FUNCTION (נפרס כאן) | POST (הניתוח שלך) |
|---|---|---|
| הכן מצב, כמעגל או כמצב מכפלה, עם בעיטה מקומית אופציונלית | סינתזת Trotter → כיווץ AQC → הרצה על statevector, fake, או runtime, המחזירה | עבור פיזור נויטרונים, או מגנטיזציה, תעבורה, דינמיקת quench, וכן הלאה |
התבנית מפורסמת במאגר תבניות פונקציית Qiskit, לצד תבניות היישום האחרות. מחברת זו פורסת אותה לחשבון Qiskit Serverless שלך. הרץ אותה פעם אחת, וכל מחברת תוכל אז לקרוא לפונקציה עם serverless.load("aqc-dynamics-function").
לדוגמה מדעית מפורטת, ראה סימולציה של פיזור נויטרונים עם זרימת עבודה של AQC + Trotter dynamics Serverless, שקוראת לפונקציה זו כדי לחשב את גורם המבנה הדינמי של KCuF. מחברת זו עוסקת בפריסה ובחוזה הקלט במקום זאת.
דרישות
לפני שמתחילים, ודא שיש לך את הבאים בסביבת הליבה של מחברת זו:
-
Qiskit SDK גרסה 2.0 ואילך (
pip install qiskit). -
לקוח Qiskit IBM Catalog (
pip install qiskit-ibm-catalog), שפורס ומריץ עומסי עבודה על Qiskit Serverless.
התלויות המדעיות של הפונקציה עצמה (qiskit-addon-aqc-tensor, cotengrust, qiskit-aer) אינן צריכות להיות מותקנות מקומית.
קבל את קבצי המקור של התבנית
הפונקציה היא חבילת Python קטנה ש-Qiskit Serverless מריצה בענן, כך שהמקור שלה חייב להתקיים כקבצים מקומיים שמועלים בזמן הפריסה. החבילה מפורסמת במאגר תבניות פונקציית Qiskit.
הורד את source_files
ההורדה היא קובץ zip יחיד, הנקרא על שם הנתיב המלא של הספרייה במאגר:
qiskit-community qiskit-function-templates main physics aqc_trotter source_files.zip
-
חלץ אותו לתוך הספרייה שמכילה את מחברת זו.
-
שנה את שם התיקייה שחולצה מהשם הארוך הזה ל-
source_files.
ספריית העבודה שלך תיראה אז כך:
your-working-directory/
├── function-template-aqc-trotter.ipynb <- this notebook
└── source_files/ <- the renamed folder
├── __init__.py
├── program.py
└── source/
├── __init__.py
├── _serverless.py
├── app_function.py
├── aqc.py
├── build.py
├── execute.py
└── hamiltonian.py
השם חייב להיות בדיוק source_files, מכיוון שזהו ה-working_dir שהשלב 3 מעלה.
program.py היא נקודת הכניסה שה-gateway קורא לה. כל מה שתחת source/ הוא המימוש, מחולק לפי שלב: סינתזת המילטוניאן ו-Trotter, כיווץ AQC, והרצה. אין צורך לערוך אף אחד מהם כדי להריץ את הדוגמאות שבאות בהמשך. שלב 3 מעלה את כל הספרייה, כך שיש לחזור על שלב זה בכל פעם שאתה משנה קובץ.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-ibm-catalog
1. אימות
השתמש ב-qiskit-ibm-catalog כדי להתאמת ל-QiskitServerless עם מפתח ה-API שלך (טוקן) ו-CRN (מופע), שאותם אפשר למצוא בלוח המחוונים של IBM Quantum® Platform. עם פרטי הכניסה האלה אפשר ליצור מופע של הלקוח ללא שרת מקומית כדי להעלות או להריץ את הפונקציה שנבחרה:
from qiskit_ibm_catalog import QiskitServerless
serverless = QiskitServerless(channel="ibm_quantum_platform", token="MY_TOKEN", instance="MY_CRN")
אפשר אופציונלית להשתמש ב-save_account() כדי לשמור את פרטי הכניסה שלך בסביבה המקומית שלך (ראה את המדריך הגדרת חשבון IBM Cloud® שלך). שים לב שזה כותב את פרטי הכניסה שלך לאותו קובץ כמו QiskitRuntimeService.save_account():
QiskitServerless.save_account(channel="ibm_quantum_platform", token="MY_TOKEN", instance="MY_CRN")
אם החשבון שמור, אין צורך לספק את הטוקן כדי להתאמת:
from qiskit_ibm_catalog import QiskitServerless
# Authenticate to the remote cluster
# In this case, loading a saved account
serverless = QiskitServerless()
# REPLACE WITH YOUR OWN CREDENTIALS or SAVED ACCOUNT
# serverless = QiskitServerless(channel="ibm_quantum_platform", token="MY_TOKEN", instance="MY_CRN")
2. הכרזת תלויות
חבילות שהפונקציה זקוקה להן מעבר לאימג' ה-serverless הבסיסי המנוהל.
ה-gateway מתקין רק שמות ברשימת ההיתרים שלו (requirements-dynamic-dependencies.txt), התואמים לפי שם חבילה ומקובעים לגרסה המותרת עם ==. כל דבר אחר חייב להגיע באופן טרנזיטיבי (כתלות של חבילה ברשימת ההיתרים). התחביר [extras] נשמר: qiskit-addon-aqc-tensor[quimb-jax] הוא מה שמתקין את quimb ואת jax. cotengrust נחוץ ליעילות זיכרון במהלך סימולציית רשת טנזורים. qiskit-aer מופיע בנפרד עבור ה-backend fake (סימולציה מקומית עם רעש).
DEPENDENCIES = [
"qiskit-addon-aqc-tensor[quimb-jax]==0.3.1",
"qiskit-aer==0.17.2",
"cotengrust==0.2.0",
]
3. הגדרה והעלאה של הפונקציה
from qiskit_ibm_catalog import QiskitFunction
fn = QiskitFunction(
title="aqc-dynamics-function",
entrypoint="program.py",
working_dir="source_files/",
dependencies=DEPENDENCIES,
)
serverless.upload(fn)
QiskitFunction(aqc-dynamics-function)
4. ודא שהיא נרשמה
next(p for p in serverless.list() if p.title == "aqc-dynamics-function")
QiskitFunction(aqc-dynamics-function)
מדריך עזר לפונקציה
זוהי הקדמה קצרה. כל שדה מתועד במלואו בREADME של תבנית AQC Dynamics: טבלת הקלטים המלאה עם כללי האימות שלה, שדות הפלט, ה-backends להרצה, ודוגמאות מפורטות נוספות. מה שבא בהמשך היא הגרסה הקצרה, מספיקה כדי לקרוא את הדוגמאות שבאות בהמשך.
קלטים
כל הרצה היא קריאה בודדת ל-fn.run(...). רק שלושת הקלטים הראשונים בטבלה נדרשים: hamiltonian, t_steps, ו-aqc_segments. כל מה שאחריהם אופציונלי וחוזר לברירת המחדל שמוצגת, כך שקריאה מינימלית היא שלושה ארגומנטים ושאר הטבלה היא הפונקציונליות שאפשר לבחור בה. num_qubits של ההמילטוניאן קובע את אורך השרשרת, כך שאין קלט גודל נפרד.
| קלט | ברירת מחדל | תיאור |
|---|---|---|
hamiltonian | נדרש | המילטוניאן פאולי חד-ממדי עם שכנים קרובים כ-SparsePauliOp. מחרוזות הן אופרטורי פאולי, כך שאין גורם משתמע של חצי. |
t_steps | נדרש | סך צעדי Trotter. מתפתח עד T = t_steps * dt ומדווח על כל תצפית בכל t_k = k * dt. |
aqc_segments | נדרש | תוכנית כיווץ: רשימה של {"n_steps": k, "ansatz_steps": m}. sum(n_steps) צעדים מכווצים; השאר רצים כ-Trotter רגיל. |
dt | 0.2 | הזמן הפיזי שמתקדם על ידי צעד Trotter אחד. |
initial_state | |0...0> | QuantumCircuit מוכן להתפתחות בזמן. שלב כל דחיפה מקומית לתוך המעגל הזה. |
observables | Z לכל אתר | כל מה ש-EstimatorV2 מקבל כארגומנט ה-observables שלו. תצפית אחת לכל עמודת פלט. |
trotter_options | Suzuki מסדר שני | {"method": ..., "synthesis_settings": {...}}. reps ו-time בבעלות הפונקציה. |
aqc_options | ראה תיאור | max_bond (32), cutoff (1e-8), autodiff_backend ("jax"), fidelity_target (None), optimizer_settings (L-BFGS-B, jac=True, maxiter=300). |
estimator_options | DD, twirling, TREX | EstimatorV2.options, מועבר כפי שהוא. מילון שסופק מחליף את ברירות המחדל לחלוטין במקום להתמזג איתן. |
transpiler_options | {"optimization_level": 3} | ארגומנטי מילת מפתח של generate_preset_pass_manager. backend ו-target נדחים, מכיוון שנתיב ההרצה הוא שאחראי עליהם. |
backend | "runtime" | "statevector", "fake", או "runtime". |
backend_name | הפחות עמוס | שם backend של IBM® עבור runtime, או backend מדומה בשם. |
batches | 1 | פצל את המעגלים על פני N עבודות runtime. אצווה אחת מגישה עבודה בודדת ולא יוצרת session. |
parallel_sim | False | פרוס את נתיבי הסימולטור המקומי על פני כל הליבות הזמינות עם Ray. אין השפעה על runtime. |
return_circuits | False | החזר את מעגלי AQC + Trotter הלוגיים בתוצאה לצד סדרת התצפית. |
backends להרצה
שלושת הנתיבים חולקים אותו קוד ואותן הגדרות מיטיגציה. הם נבדלים רק במקום שבו המעגלים רצים.
backend | מה זה | פרטי כניסה | הערות |
|---|---|---|---|
"statevector" | StatevectorEstimator מדויק | חשבון Serverless בלבד | נתיב הייחוס המדויק. ללא זמן QPU. |
"fake" | סימולציה מקומית עם רעש על backend מדומה של Qiskit | חשבון Serverless בלבד | חזרה נאמנה של נתיב ה-runtime המוקהה. דורש qiskit-aer. ברירת המחדל היא ה-fake_sherbrooke בעל 127 קיוביטים. |
"runtime" (ברירת מחדל) | ה-EstimatorV2 המוקהה מול QPU אמיתי | חשבון Serverless ומופע עם גישה ל-QPU | backend_name אופציונלי; השמטתו בוחרת את המכשיר הכי פחות עמוס. |
שני נתיבי הסימולטור עדיין קוראים לפונקציה שנפרסה, כך שהם זקוקים לחשבון Serverless שמור למרות שהם לא משתמשים בזמן QPU. שתי הדוגמאות שבאות בהמשך מריצות את אותו עומס עבודה על statevector תחילה, ואז על runtime.
פלט
job.result() מחזיר מילון פשוט:
{
"times": [...], # length t_steps + 1, t_k = k * dt (t=0 is the prepared state)
"expectation_values": [[...]], # shape (n_times, n_observables)
"observable_labels": [...], # for example: ["Z_0", "ZZ_0_1"]
"metadata": {
"n", "t_steps", "dt", "tier",
"aqc_compressed_steps": 5, # total compressed steps (= sum of segment n_steps)
"aqc_segments": [ # per segment: the plan plus its own results
{"n_steps": 3, "ansatz_steps": 1, "steps": [1, 2, 3], "n_params": 133,
"fidelities": {"1": ..., "2": ..., "3": ...}},
{"n_steps": 2, "ansatz_steps": 2, "steps": [4, 5], "n_params": 245,
"fidelities": {"4": ..., "5": ...}},
],
"execution_backend",
"aqc_fidelities": {"1": ..., "2": ...}, # flat per-step fidelity, all compressed steps
"circuit_stats": { # per-step 2q depth and gate count, full Trotter vs AQC
"1": {"full_trotter": {"depth_2q": ..., "num_2q_gates": ...},
"aqc_trotter": {"depth_2q": ..., "num_2q_gates": ...}},
"2": {...},
},
"warnings": [...], # non-fatal notices; for example, a cotengrust fallback
"resource_usage": { # per stage; QPU_TIME is the charged QPU time
"RUNNING: OPTIMIZING_FOR_HARDWARE": {"CPU_TIME": ...},
"RUNNING: WAITING_FOR_QPU": {"CPU_TIME": ...},
"RUNNING: EXECUTING_QPU": {"QPU_TIME": ...},
},
},
# present only when return_circuits=True
"circuits": [QuantumCircuit, ...], # one per evolved step; circuits[i] is at times[i + 1]
}
aqc_fidelities ו-circuit_stats הם השניים שכדאי לקרוא ראשונים: יחד הם מספרים לך אם הכיווץ נשאר נאמן ואם הוא באמת חסך עומק. ב-runtime, resource_usage מדווח על זמן ההמתנה בתור בנפרד מזמן ה-QPU שאתה מחויב עליו. קלט שנדחה נכשל במהירות כ-ServerlessError מובנה (קוד 4615).
דוגמת סימולטור
הרץ את הפונקציה על ה-backend המדויק statevector תחילה. היא לא מבזבזת זמן QPU ומאמתת את הפריסה מקצה לקצה. המודל כאן הוא שרשרת אייזינג עם שדה רוחבי בת שמונה קיוביטים, ו-observables הושמט כך שהפונקציה מודדת את ברירת המחדל לכל אתר.
תוכנית הכיווץ היא הקלט שכדאי להבין. כל מקטע {"n_steps": k, "ansatz_steps": m} מכווץ k צעדי Trotter עוקבים לתוך אנזץ שנבנה מיעד Trotter בן m צעדים, וכל צעד מעבר ל-sum(n_steps) רץ כ-Trotter רגיל. צעדים מוקדמים, בעלי שזירה נמוכה, מתכווצים היטב לאנזץ שכבה אחת רדוד; צעדים מאוחרים יותר, בעלי שזירה גבוהה יותר, זקוקים לאחד עמוק יותר.
from qiskit.quantum_info import SparsePauliOp
fn = serverless.load("aqc-dynamics-function")
n = 8
H = SparsePauliOp.from_sparse_list(
[("ZZ", [i, i + 1], 1.0) for i in range(n - 1)]
+ [("X", [i], 0.8) for i in range(n)],
num_qubits=n,
)
job = fn.run(
t_steps=8,
aqc_segments=[
{
"n_steps": 4,
"ansatz_steps": 1,
}, # early steps -> shallow 1-layer ansatz
{
"n_steps": 2,
"ansatz_steps": 2,
}, # later steps -> deeper 2-layer ansatz
],
hamiltonian=H,
aqc_options={"max_bond": 32},
backend="statevector",
)
print("job ID:", job.job_id)
job ID: ee1f3793-e995-427d-81d1-5924549beb38
עקוב אחרי ההרצה וקרא את התוצאה
status() מדווח הן על מחזור החיים הגס של העבודה והן על תת-הסטטוס לכל שלב שהפונקציה מפרסמת בזמן ריצתה. אותם השלבים חלים על הרצת החומרה מאוחר יותר במדריך זה:
QUEUED -> INITIALIZING -> RUNNING: OPTIMIZING_FOR_HARDWARE -> RUNNING: WAITING_FOR_QPU -> RUNNING: EXECUTING_QPU -> RUNNING: POST_PROCESSING -> DONE
ערך status() | שלב |
|---|---|
RUNNING: OPTIMIZING_FOR_HARDWARE | הכנת מצב, בניית Trotter, כיווץ AQC |
RUNNING: WAITING_FOR_QPU | בתור על ה-QPU (רק ל-backend runtime) |
RUNNING: EXECUTING_QPU | מעגלים בהרצה (סימולטורים מקומיים מסמנים זאת ישירות) |
RUNNING: POST_PROCESSING | הרכבת מילון התוצאה |
מצבים סופיים הם DONE, ERROR, ו-CANCELED. להרצת statevector זו אין תור QPU, כך שהיא מדלגת על RUNNING: WAITING_FOR_QPU. השתמש ב-job.logs() בכל שלב כדי לראות את היומנים לכל שלב, כולל הנאמנות AQC שהושגה בכל צעד.
print(job.status()) # re-run until this reports DONE
DONE
import numpy as np
result = job.result()
ev = np.array(result["expectation_values"])
print("observables:", result["observable_labels"])
print("shape:", ev.shape, "-> (n_times, n_observables)")
print("first row (t = 0, the prepared state):", np.round(ev[0], 4))
print("last row (t = t_steps * dt):", np.round(ev[-1], 4))
print(
"AQC fidelities:",
{k: round(v, 4) for k, v in result["metadata"]["aqc_fidelities"].items()},
)
# What the compression bought: 2-qubit depth at the final time step.
stats = result["metadata"]["circuit_stats"][
str(result["metadata"]["t_steps"])
]
print(
"2q depth at the final step:",
stats["full_trotter"]["depth_2q"],
"(full Trotter) ->",
stats["aqc_trotter"]["depth_2q"],
"(AQC + Trotter)",
)
observables: ['Z_0', 'Z_1', 'Z_2', 'Z_3', 'Z_4', 'Z_5', 'Z_6', 'Z_7']
shape: (9, 8) -> (n_times, n_observables)
first row (t = 0, the prepared state): [1. 1. 1. 1. 1. 1. 1. 1.]
last row (t = t_steps * dt): [0.1442 0.2956 0.4686 0.4877 0.4869 0.4686 0.2963 0.1441]
AQC fidelities: {'1': 1.0, '2': 1.0, '3': 1.0, '4': 1.0, '5': 1.0, '6': 0.9999}
2q depth at the final step: 210 (full Trotter) -> 79 (AQC + Trotter)
דוגמת חומרה
קריאה לפונקציה עם backend="runtime" מבצעת טרנספילציה והרצה על מעבד IBM Quantum אמיתי, עם מיטיגציית השגיאות המובנית של הפונקציה: decoupling דינמי (XY4), twirling של שערים, ו-twirled readout error extinction (TREX). backend_name בוחר את המכשיר; השמט אותו והפונקציה תבחר את הפחות עמוס.
אין שינוי בקוד המדעי. מה שמשתנה לעומת דוגמת הסימולטור זה אורך השרשרת, מספר צעדי הטרוטר, תוכנית הדחיסה, ה-Backend, וההגדרות המפורשות של הפחתת שגיאות שמפורטות בסעיף הבא.
קביעת גודל המשימה עבור חומרת הבקרה
estimator_options הוא הקלט ששווה לקבוע במכוון. Gate twirling בונה num_randomizations מעגלים אקראיים נפרדים עבור כל PUB, וכל המשימה, כל PUB עם כל האקראיות שלו, צריכה להיכנס לזיכרון ההוראות של מערכת הבקרה הקלאסית של ה-QPU. הפונקציה מוגדרת כברירת מחדל ל-1000 אקראיות, כך שאבולוציה של 10 צעדים שולחת 11 PUBs של 1000 מעגלים כל אחד: בערך 11,000 מופעי מעגל במשימה אחת.
אם חורגים ממה שמערכת הבקרה מחזיקה, המשימה נכשלת עם שגיאה 6073. מגבלות משימה נותן את הספים ואיך סופרים כנגדם, כאשר העיקרי הוא 26.8 מיליון הוראות מערכת בקרה לקיוביט, שמיושם לפי משימה ולא לפי PUB. Dynamical decoupling מוסיף שערים שנספרים לכך.
שני קלטים שולטים בגודל:
-
estimator_optionsקובע את תקציב היריות. סך היריות הואnum_randomizations * shots_per_randomization, כך שאפשר להחליף בין אקראיות ליריות לכל אקראיות, לשמור על הסטטיסטיקה, ועדיין לצמצם את התוכנית. התא הבא משתמש ב-100 אקראיות עם 200 יריות כל אחת, שזה 20,000 יריות לכל תצפית ובערך עשירית ממופעי המעגל שברירת המחדל היתה שולחת. ראה TwirlingOptions ו-אפשרויות Estimator לקבוצת השדות המלאה. -
batchesמפצל את ה-PUBs על פני אותו מספר של משימות runtime נפרדות, שזה בדיוק התיקון ששגיאה 6073 עצמה מציעה, וזו הסיבה שהמסגרת לפי-משימה חשובה. הגדרתbatches=4שולחת בערך שלושה PUBs למשימה במקום אחת עשרה בבת אחת, והמשימות יוצאות יחד באצווה אחת כך שהקבוצה נכנסת לתור פעם אחת במקום שכל משימה תיכנס לתור בנפרד.
זכור שאספקת estimator_options מחליפה את ברירות המחדל של הפונקציה לחלוטין במקום להתמזג איתן, כך ש-dynamical decoupling ו-TREX מוגדרים מחדש בתא הבא כדי לשמור אותם פעילים.
from qiskit.quantum_info import SparsePauliOp
fn = serverless.load("aqc-dynamics-function")
n = 10
H = SparsePauliOp.from_sparse_list(
[("ZZ", [i, i + 1], 1.0) for i in range(n - 1)]
+ [("X", [i], 0.8) for i in range(n)],
num_qubits=n,
)
job = fn.run(
t_steps=10,
aqc_segments=[
{
"n_steps": 3,
"ansatz_steps": 1,
}, # early steps -> shallow 1-layer ansatz
{
"n_steps": 3,
"ansatz_steps": 2,
}, # later steps -> deeper 2-layer ansatz
],
hamiltonian=H,
aqc_options={"max_bond": 32},
backend="runtime",
backend_name="ibm_marrakesh",
# The function defaults to 1000 twirling randomizations, which was too large
# for this device. Total shots is num_randomizations *
# shots_per_randomization, so this is 20,000 shots per observable.
estimator_options={
"dynamical_decoupling": {"enable": True, "sequence_type": "XY4"},
"twirling": {
"enable_gates": True,
"num_randomizations": 100,
"shots_per_randomization": 200,
},
"resilience": {"measure_mitigation": True},
},
)
print("job ID (save this to reconnect later):", job.job_id)
job ID (save this to reconnect later): 7229a8bf-9f83-4785-8dd4-489844abc2d9
הרצה על חומרה אינה מהירה, ורוב הזמן הוא קלאסי ולא על ה-QPU. דחיסת AQC רצה בתוך הפונקציה לפני שמשהו מגיע ל-QPU, ותור ה-QPU מתווסף לכך. אין צורך לשמור את המחברת או הליבה הזו פתוחה בזמן שהיא רצה.
העתק את מזהה המשימה שהודפס על ידי התא הקודם ושמור אותו. שלושת התאים הבאים מאפשרים לך לחזור להרצה מאוחר יותר:
-
התחברות מחדש, נדרש רק בהפעלת ליבה חדשה: הרץ שוב את התא אימות כדי ליצור מחדש את
serverless, ואז בנה מחדש את מזהה ה-jobמהמזהה ששמרת. דלג על התא הזה אם אתה עדיין באותה הפעלה שבה שלחת את המשימה, כי המזהה כבר פעיל. -
בדוק סטטוס: הרץ שוב עד שהוא מדווח
DONE. -
שלוף את התוצאה: הרץ רק לאחר שהסטטוס הוא
DONE.
הדבק את המזהה השמור שלך במקום ה-placeholder בתא ההתחברות מחדש הבא.
# Reconnect to a previously submitted job by its ID. Only needed in a NEW kernel
# session; if you are still in the session where you submitted, the `job` handle
# from the preceding cell is already live, so skip this cell. Replace the ID that follows with your own.
job = serverless.get_job_by_id("<your job ID>")
# Re-run this until it reports DONE, then fetch the result in the following cell.
print(job.status())
DONE
import numpy as np
# Run this only once the preceding status cell reports DONE. result() blocks until
# the job finishes, so calling it earlier just waits.
result = job.result()
ev = np.array(result["expectation_values"])
print("backend:", result["metadata"]["execution_backend"])
print("shape:", ev.shape, "-> (n_times, n_observables)")
print("last row (t = t_steps * dt):", np.round(ev[-1], 4))
print(
"AQC fidelities:",
{k: round(v, 4) for k, v in result["metadata"]["aqc_fidelities"].items()},
)
# What the compression bought: 2-qubit depth at the final time step.
stats = result["metadata"]["circuit_stats"][
str(result["metadata"]["t_steps"])
]
print(
"2q depth at the final step:",
stats["full_trotter"]["depth_2q"],
"(full Trotter) ->",
stats["aqc_trotter"]["depth_2q"],
"(AQC + Trotter)",
)
backend: runtime
shape: (11, 10) -> (n_times, n_observables)
last row (t = t_steps * dt): [0.1504 0.1361 0.218 0.2144 0.2275 0.1783 0.1749 0.1599 0.0915 0.0922]
AQC fidelities: {'1': 1.0, '2': 1.0, '3': 1.0, '4': 1.0, '5': 0.9999, '6': 0.9999}
2q depth at the final step: 342 (full Trotter) -> 171 (AQC + Trotter)
צעדים הבאים
-
עבור על סימולציה של פיזור נויטרונים עם תהליך עבודה AQC + Trotter dynamics Serverless, הדוגמה הנלווית שקוראת לפונקציה הפרוסה הזו כדי לחשב את גורם המבנה הדינמי של KCuF.
-
קרא את תבנית AQC Dynamics ב-GitHub לחוזה הקלט והפלט המלא, דוגמאות נוספות, ופרטי ציטוט.
-
עיין במאגר תבניות Qiskit Function עבור תבניות יישום אחרות שנבנו באותו אופן.
-
קרא את מדריך Qiskit Serverless לניהול פונקציות פרוסות.
-
העמק בשלב דחיסת ה-AQC עם תיעוד Qiskit addon: AQC-Tensor.