הרצת מעגלים דינמיים
גרסאות חבילות
הקוד בדף זה פותח תוך שימוש בדרישות הבאות. אנחנו ממליצים להשתמש בגרסאות אלה או חדשות יותר.
qiskit[all]~=2.4.0
qiskit-ibm-runtime~=0.46.1
מעגלים דינמיים הם כלים חזקים שבהם אפשר למדוד Qubits באמצע הרצת מעגל קוונטי ולאחר מכן לבצע פעולות לוגיקה קלאסית בתוך המעגל, על בסיס תוצאת מדידות אלה באמצע המעגל. תהליך זה מכונה גם classical feedforward. בעוד שאלה ימים מוקדמים להבין כיצד להפיק את המרב ממעגלים דינמיים, קהילת המחקר הקוונטי כבר זיהתה מספר מקרי שימוש, כגון הבאים:
- הכנת מצב קוונטי יעילה, כגון מצב GHZ, מצב W (למידע נוסף על מצב W, ראו גם "State preparation by shallow circuits using feed forward"), ומחלקה רחבה של מצבי מכפלת מטריצה
- אנטנגלמנט לטווח ארוך יעיל בין Qubits על אותו שבב באמצעות מעגלים רדודים
- דגימה יעילה של מעגלים דמויי IQP
השיפורים שמביאים מעגלים דינמיים, עם זאת, כרוכים בפשרות. מדידות באמצע מעגל ופעולות קלאסיות בדרך כלל כוללות זמן ביצוע ארוך יותר מאשר שערים דו-Qubit, ועלייה זו בזמן עשויה לבטל את היתרונות של עומק מעגל מופחת. לכן, הפחתת אורך מדידת אמצע מעגל היא תחום מיקוד לשיפור כאשר IBM Quantum® משחרר את הגרסה החדשה של מעגלים דינמיים. לגבי הגבלות נוספות בשימוש במעגלים דינמיים, ראו את טבלת תאימות התכונות של Estimator או Sampler.
מפרט OpenQASM 3 מגדיר מספר מבני זרימת בקרה, אך Qiskit Runtime כרגע תומך רק בפקודת ה-if המותנית. ב-Qiskit SDK, זה מתאים למתודת if_test על QuantumCircuit. מתודה זו מחזירה context manager ובדרך כלל משמשת בהצהרת with. מדריך זה מסביר כיצד להשתמש בהצהרה מותנית זו.
דוגמאות הקוד במדריך זה משתמשות בהוראת המדידה הרגילה למדידות אמצע מעגל. עם זאת, מומלץ להשתמש בהוראת MidCircuitMeasure במקום זאת, אם ה-Backend תומך בה. ראו את חלק מדידות אמצע מעגל לפרטים.
מצא Backends שתומכים במעגלים דינמיים
כדי למצוא את כל ה-Backends שהחשבון שלך יכול לגשת אליהם ותומכים במעגלים דינמיים, הרץ קוד כמו הבא. דוגמה זו מניחה שהשמרת את אישורי הכניסה שלך. אפשר גם לציין אישורים במפורש בעת אתחול חשבון שירות Qiskit Runtime. זה יאפשר לך לצפות ב-Backends הזמינים על מופע או סוג תוכנית ספציפיים, לדוגמה.
- ה-Backends הזמינים לחשבון תלויים במופע שצוין באישורים.
- הגרסה החדשה של מעגלים דינמיים זמינה כעת לכל המשתמשים על כל ה-Backends. ראו ההכרזה לפרטים נוספים.
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-runtime
# This cell is hidden from users. It hides all those "...instance was not set..." warnings.
import warnings
warnings.filterwarnings("ignore", message=".*Instance was not set*")
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
dc_backends = service.backends(dynamic_circuits=True)
print(dc_backends)
[<IBMBackend('ibm_pittsburgh')>, <IBMBackend('ibm_kingston')>, <IBMBackend('ibm_marrakesh')>, <IBMBackend('ibm_fez')>, <IBMBackend('ibm_boston')>]
מדידות אמצע מעגל
לפני qiskit-ibm-runtime v0.43.0, measure היה הוראת המדידה היחידה ב-Qiskit. עם זאת, למדידות אמצע מעגל יש דרישות כוונון שונות ממדידות סופניות (מדידות שמתרחשות בסוף מעגל). לדוגמה, צריך לשקול את משך ההוראה בכוונון מדידת אמצע מעגל כי הוראות ארוכות יותר גורמות למעגלים רועשים יותר. לא צריך לשקול את משך ההוראה עבור מדידות סופניות מכיוון שאין הוראות אחרי מדידות סופניות.
הוראת ה-MidCircuitMeasure ממפה להוראת ה-measure_2 המדווחת ב-supported_instructions של ה-Backend. עם זאת, measure_2 אינה נתמכת על כל ה-Backends. השתמש ב-service.backends(filters=lambda b: "measure_2" in b.supported_instructions) כדי למצוא Backends שתומכים בה. מדידות חדשות עשויות להתווסף בעתיד, אך אין ערובה לכך.
מתודת MidCircuitMeasure
ב-qiskit-ibm-runtime v0.43.0, הוצגה הוראת ה-MidCircuitMeasure. כשמה מעיד, זו הוראת מדידה חדשה שמותאמת לאמצע מעגל על QPUs של IBM®. בעוד שניתן להשתמש ב-QuantumCircuit.measure למדידת אמצע מעגל, בגלל עיצובה, MidCircuitMeasure בדרך כלל בחירה טובה יותר. לדוגמה, היא מוסיפה פחות תקורה למעגל שלך מאשר בשימוש ב-QuantumCircuit.measure.
from qiskit import QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime.circuit import MidCircuitMeasure
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, dynamic_circuits=True
)
circ = QuantumCircuit(2, 2)
circ.x(0)
circ.append(MidCircuitMeasure(), [0], [0])
# circ.measure([0], [0])
# circ.measure_all()
print(circ.draw(cregbundle=False))
┌───┐┌────────────┐
q_0: ┤ X ├┤0 ├
└───┘│ │
q_1: ─────┤ Measure_2 ├
│ │
c_0: ═════╡0 ╞
└────────────┘
c_1: ═══════════════════
- חייב להיות לפחות רגיסטר קלאסי אחד כדי להשתמש במדידות.
- ה-primitive של Sampler דורש מדידות מעגל. ניתן להוסיף מדידות מעגל עם ה-primitive של Estimator, אך הן מתעלמות.
Store
עם גרסה 0.47.0 ומעלה של qiskit-ibm-runtime, אפשר להשתמש בהוראת store כדי לשמור את תוצאת ביטוי קלאסי, אם הביטוי הזה ישמש שוב ושוב. פעולות מקבילות אוטומטית, מה שהופך את הקוד שלך ליעיל הרבה יותר בזמן ריצה.
למידע נוסף, ראו את מדריך Classical feedforward וזרימת בקרה.
כשמשתמשים ב-store כדי לשמור ערך לרגיסטר קלאסי על Backend אמיתי, הערך הזה נשמר בזיכרון רק במהלך הביצוע ואינו מועתק או מוחזר בתוצאת העבודה.
לדוגמה, בקוד הבא, ל-temp יש את אותו ערך כמו creg במהלך הביצוע, וה-if_test עובד כצפוי. אבל לאחר סיום העבודה, ה-temp BitArray שמוחזר בתוצאת העבודה אינו מכיל את ערך ה-creg. כלומר, job.result()[0].data.temp הוא 0.
creg = ClassicalRegister(3, "c")
temp = ClassicalRegister(3, "temp")
...
qc.store(temp, creg)
with circuit.if_test((temp, 0b001)):
...
דוגמה מלאה
הקוד הבא יוצר ומריץ מעגל דינמי על חומרת IBM®.
from qiskit_ibm_runtime import SamplerV2, QiskitRuntimeService
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.transpiler import generate_preset_pass_manager
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, dynamic_circuits=True
)
# Create a dynamic circuit
qubits = QuantumRegister(1)
clbits = ClassicalRegister(1)
qc = QuantumCircuit(qubits, clbits)
(q0,) = qubits
(c0,) = clbits
qc.h(q0)
qc.measure(q0, c0)
with qc.if_test((c0, 1)):
qc.x(q0)
qc.measure(q0, c0)
# Convert to an ISA circuit for the given backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(qc)
# Generate samplers for backend targets
sampler = SamplerV2(backend)
# Submit jobs
sampler_job = sampler.run([isa_circuit])
result = sampler_job.result()
print(
f">>> {' Job ID:':<10} {sampler_job.job_id()} ({sampler_job.status()})"
)
>>> Job ID: d88cakp789is7391vq0g (DONE)
מגבלות Qiskit Runtime
שים לב לאילוצים הבאים בעת הרצת מעגלים דינמיים ב-Qiskit Runtime.
-
בגלל הזיכרון הפיזי המוגבל על אלקטרוניקת הבקרה, יש גם מגבלה על מספר הצהרות ה-
ifוגודל האופרנדים שלהן. מגבלה זו היא פונקציה של מספר ה-broadcasts ומספר הסיביות המשודרות בעבודה (לא במעגל).בעיבוד תנאי
if, נתוני מדידה צריכים להיות מועברים ללוגיקת הבקרה כדי לבצע את ההערכה הזו. broadcast הוא העברה של נתונים קלאסיים ייחודיים, ו-broadcasted bits הוא מספר הסיביות הקלאסיות שמועברות. שקול את הבא:c0 = ClassicalRegister(3)c1 = ClassicalRegister(5)...with circuit.if_test((c0, 1)) ...with circuit.if_test((c0, 3)) ...with circuit.if_test((c1[2], 1)) ...בדוגמת הקוד הקודמת, שתי אובייקטי ה-
if_testהראשונים עלc0נחשבים ל-broadcast אחד מכיוון שתוכן ה-c0לא השתנה, ולכן אין צורך לשדר אותו מחדש. ה-if_testעלc1הוא broadcast שני. הראשון משדר את כל שלוש הסיביות ב-c0והשני משדר רק סיבית אחת, ובסך הכל ארבע סיביות משודרות.כרגע, אם משדרים 60 סיביות בכל פעם, אז לעבודה יכולים להיות בערך 300 broadcasts. עם זאת, אם משדרים רק סיבית אחת בכל פעם, לעבודה יכולים להיות 2400 broadcasts.
-
האופרנד שנעשה בו שימוש בהצהרת
if_testחייב להיות 32 סיביות או פחות. לכן, אם משוויםClassicalRegisterשלם, גודל ה-ClassicalRegisterהזה חייב להיות 32 סיביות או פחות. אם משווים רק סיבית בודדת מ-ClassicalRegister, עם זאת, ה-ClassicalRegisterהזה יכול להיות בכל גודל (מכיוון שהאופרנד הוא רק סיבית אחת).לדוגמה, בלוק הקוד "לא חוקי" לא עובד כי
crגדול מ-32 סיביות. ניתן, עם זאת, להשתמש ברגיסטר קלאסי רחב מ-32 סיביות אם בודקים רק סיבית אחת, כפי שמוצג בבלוק הקוד "חוקי".- לא חוקי
- חוקי
cr = ClassicalRegister(50)qr = QuantumRegister(50)circuit = QuantumCircuit(qr, cr)...circ.measure(qr, cr)with circ.if_test((cr, 15)):...cr = ClassicalRegister(50)qr = QuantumRegister(50)circuit = QuantumCircuit(qr, cr)...circ.measure(qr, cr)with circ.if_test((cr[5], 1)):... -
תנאים מקוננים אינם מותרים. לדוגמה, בלוק הקוד הבא לא יעבוד מכיוון שיש לו
if_testבתוךif_testאחר:- לא חוקי
- חוקי
c1 = ClassicalRegister(1, "c1")c2 = ClassicalRegister(2, "c2")...with circ.if_test((c1, 1)):with circ.if_test(c2, 1)):...cr = ClassicalRegister(2)...with circuit.if_test((cr, 0b11)):... -
resetאו מדידות בתוך תנאים אינם נתמכים. -
פעולות אריתמטיות אינן נתמכות.
-
ראו את טבלת תכונות OpenQASM 3 כדי לקבוע אילו תכונות OpenQASM 3 נתמכות ב-Qiskit וב-Qiskit Runtime.
-
כאשר OpenQASM 3 (במקום
QuantumCircuit) משמש כפורמט קלט להעברת מעגלים ל-primitives של Qiskit Runtime, רק הוראות שניתן לטעון ל-Qiskit נתמכות. פעולות קלאסיות, לדוגמה, אינן נתמכות מכיוון שלא ניתן לטעון אותן ל-Qiskit. ראו ייבוא תוכנית OpenQASM 3 ל-Qiskit למידע נוסף. -
הוראות
for,whileו-switchאינן נתמכות.
שימוש במעגלים דינמיים עם Estimator
מכיוון ש-Estimator אינו תומך במעגלים דינמיים, ניתן להשתמש ב-Sampler ולבנות מעגלי מדידה משלך במקום.
כדי לשחזר את התנהגות Estimator, עקוב אחר תהליך זה:
- קבץ את איברי כל ה-observables לחלוקה. ניתן לעשות זאת באמצעות ה-API של
PauliList, לדוגמה.הערהניתן להשתמש במאפיין ה-primitive של
BitArrayלחישוב ערכי הציפייה של ה-observables שסופקו. - הרץ מעגל שינוי בסיס אחד לכל חלוקה (איזה שינוי בסיס שצריך לבצע לכל חלוקה). ראו את מודול
measurement_basesשל תוסף כלי השירות למדידה למידע נוסף. לפרטים נוספים, ראו את התיעוד לחבילת כלי השירות של Qiskit addon. - חבר בחזרה את התוצאות לכל חלוקה.
הגבלות
עיין בכל טבלת תאימות תכונות כדי להבין הגבלות בשימוש במעגלים דינמיים. שים לב שתאימות תכונות אינה תלויה ב-primitive.
השלבים הבאים
- למד כיצד ליישם dynamical decoupling מדויק באמצעות stretch.
- עיין במדריך classical feedforward וזרימת בקרה.
- השתמש בהצגת חזותית של לוח זמנים מעגל לדיבוג ואופטימיזציה של המעגלים הדינמיים שלך.
- לא כל הפונקציות תואמות למעגלים דינמיים. בדוק את חלק תאימות התכונות עבור Sampler או Executor לפרטים.