דלג לתוכן הראשי

הפחתת שגיאות עם פונקציית IBM Circuit

הערה

פונקציות Qiskit הן תכונה ניסיונית הזמינה רק למשתמשי IBM Quantum® Premium Plan, Flex Plan ו-On-Prem (באמצעות IBM Quantum Platform API). הן בשלב פרסום מקדים ועשויות להשתנות.

אומדן שימוש: 26 דקות על מעבד Eagle (הערה: זהו אומדן בלבד. זמן הריצה שלך עשוי להשתנות.)

מדריך זה מציג דוגמה לבניה והרצה של זרימת עבודה באמצעות פונקציית IBM Circuit. פונקציה זו מקבלת Primitive Unified Blocs (PUBs) כקלט ומחזירה ערכי תוחלת מופחתי שגיאות כפלט. היא מספקת צינור אוטומטי ומותאם להמרת מעגלים והרצה על חומרה קוונטית, כך שחוקרים יכולים להתמקד בגילוי אלגוריתמים ויישומים.

בקרו בתיעוד למידע על מבוא לפונקציות Qiskit ולמדו איך להתחיל עם פונקציית IBM Circuit.

רקע

מדריך זה עוסק במעגל כללי יעיל-חומרה לאבולוציה בזמן מסוג Trotter עבור מודל Ising בשדה רוחבי דו-ממדי, ומחשב את המגנטיות הגלובלית. מעגל כזה שימושי בתחומי יישום שונים כמו פיזיקה של חומר מרוכז, כימיה ולמידת מכונה. למידע נוסף על המבנה של מודל זה, ראו Nature 618, 500–505 (2023).

פונקציית IBM Circuit משלבת יכולות משירות ה-transpiler של Qiskit ומ-Qiskit Runtime Estimator כדי לספק ממשק פשוט להרצת מעגלים. הפונקציה מבצעת transpilation, דיכוי שגיאות, הפחתת שגיאות והרצת מעגלים במסגרת שירות מנוהל אחד, כך שנוכל להתמקד במיפוי הבעיה למעגלים במקום לבנות כל שלב בתבנית בעצמנו.

דרישות

לפני תחילת המדריך, וודאו שיש לכם את הדברים הבאים מותקנים:

  • Qiskit SDK גרסה 1.2 ומעלה (pip install qiskit)
  • Qiskit Runtime גרסה 0.28 ומעלה (pip install qiskit-ibm-runtime)
  • IBM Qiskit Functions Catalog client גרסה 0.0.0 ומעלה (pip install qiskit-ibm-catalog)
  • Qiskit Aer גרסה 0.15.0 ומעלה (pip install qiskit-aer)

הגדרה

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-ibm-catalog qiskit-ibm-runtime rustworkx
import rustworkx
from collections import defaultdict
from numpy import pi, mean

from qiskit_ibm_runtime import QiskitRuntimeService

from qiskit_ibm_catalog import QiskitFunctionsCatalog

from qiskit.circuit import QuantumCircuit, Parameter
from qiskit.quantum_info import SparsePauliOp

שלב 1: מיפוי קלט קלאסי לבעיה קוונטית

  • קלט: פרמטרים ליצירת המעגל הקוונטי
  • פלט: מעגל מופשט ואובסרבלים

בניית המעגל

המעגל שניצור הוא מעגל יעיל-חומרה לאבולוציה בזמן מסוג Trotter עבור מודל Ising בשדה רוחבי דו-ממדי. נתחיל בבחירת backend. המאפיינים של backend זה (כלומר, מפת הצימוד שלו) ישמשו להגדרת הבעיה הקוונטית ולהבטחת יעילות חומרה.

service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
)

לאחר מכן, נשיג את מפת הצימוד מה-backend.

coupling_graph = backend.coupling_map.graph.to_undirected(multigraph=False)
layer_couplings = defaultdict(list)

אנו רוצים להיות זהירים באופן שבו אנו מעצבים את השכבות של המעגל. נעשה זאת על ידי צביעת הקצוות של מפת הצימוד (כלומר, קיבוץ הקצוות הלא-חופפים) ונשתמש בצביעה זו כדי למקם שערים במעגל בצורה יעילה יותר. זה יוביל למעגל רדוד יותר עם שכבות של שערים שניתן להריץ בו-זמנית על החומרה.

edge_coloring = rustworkx.graph_bipartite_edge_color(coupling_graph)

for edge_idx, color in edge_coloring.items():
layer_couplings[color].append(
coupling_graph.get_edge_endpoints_by_index(edge_idx)
)
layer_couplings = [
sorted(layer_couplings[i]) for i in sorted(layer_couplings.keys())
]

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

def construct_trotter_circuit(
num_qubits: int,
num_trotter_steps: int,
layer_couplings: list,
barrier: bool = True,
) -> QuantumCircuit:
theta, phi = Parameter("theta"), Parameter("phi")
circuit = QuantumCircuit(num_qubits)

for _ in range(num_trotter_steps):
circuit.rx(theta, range(num_qubits))
for layer in layer_couplings:
for edge in layer:
if edge[0] < num_qubits and edge[1] < num_qubits:
circuit.rzz(phi, edge[0], edge[1])
if barrier:
circuit.barrier()

return circuit

נבחר את מספר ה-qubits ושלבי ה-trotter ולאחר מכן נבנה את המעגל.

num_qubits = 100
num_trotter_steps = 2

circuit = construct_trotter_circuit(
num_qubits, num_trotter_steps, layer_couplings
)
circuit.draw("mpl", fold=-1)

Output of the previous code cell

כדי לבצע benchmark לאיכות ההרצה, עלינו להשוות אותה לתוצאה האידיאלית. המעגל שנבחר חורג מסימולציה קלאסית בכוח גס. לכן, נקבע את הפרמטרים של כל שערי ה-Rx במעגל ל-00, ושל כל שערי ה-Rzz ל-π\pi. זה הופך את המעגל ל-Clifford, מה שמאפשר לבצע את הסימולציה האידיאלית ולקבל את התוצאה האידיאלית להשוואה. במקרה זה, אנו יודעים שהתוצאה תהיה 1.0.

parameters = [0, pi]

בניית האובסרבל

ראשית, נחשב את המגנטיות הגלובלית לאורך z^\hat{z} עבור בעיית NN-qubit: Mz=i=1NZi/NM_z = \sum_{i=1}^N \langle Z_i \rangle / N. זה דורש תחילה חישוב של המגנטיות החד-אתרית Zi\langle Z_i \rangle עבור כל qubit ii, שמוגדרת בקוד הבא.

observables = []
for i in range(num_qubits):
obs = "I" * (i) + "Z" + "I" * (num_qubits - i - 1)
observables.append(SparsePauliOp(obs))

print(observables[0])
SparsePauliOp(['ZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
coeffs=[1.+0.j])

שלבים 2 ו-3: אופטימיזציה של הבעיה להרצה על חומרה קוונטית והרצה עם פונקציית IBM Circuit

  • קלט: מעגל מופשט ואובסרבלים
  • פלט: ערכי תוחלת מופחתי שגיאות

כעת, נוכל להעביר את המעגל המופשט והאובסרבלים לפונקציית IBM Circuit. היא תטפל ב-transpilation ובהרצה על חומרה קוונטית עבורנו ותחזיר ערכי תוחלת מופחתי שגיאות. ראשית, נטען את הפונקציה מ-IBM Qiskit Functions Catalog.

catalog = QiskitFunctionsCatalog(
token="<YOUR_API_KEY>"
) # Use the 44-character API_KEY you created and saved from the IBM Quantum Platform Home dashboard
function = catalog.load("ibm/circuit-function")

פונקציית IBM Circuit מקבלת pubs, backend_name, וגם קלטים אופציונליים להגדרת transpilation, הפחתת שגיאות ועוד. ניצור את ה-pub מהמעגל המופשט, האובסרבלים ופרמטרי המעגל. שם ה-backend צריך להיות מצוין כמחרוזת.

pubs = [(circuit, observables, parameters)]
backend_name = backend.name

נוכל גם להגדיר את ה-options עבור transpilation, דיכוי שגיאות והפחתת שגיאות. הגדרות ברירת מחדל ישמשו אם לא נרצה לציין אותן. פונקציית IBM Circuit מגיעה עם אפשרויות נפוצות ל-optimization_level, השולט בכמות האופטימיזציה של המעגל, ו-mitigation_level, שמציין כמה דיכוי והפחתת שגיאות להחיל. שימו לב ש-mitigation_level של פונקציית IBM Circuit שונה מ-resilience_level המשמש ב-Qiskit Runtime Estimator. לתיאור מפורט של אפשרויות נפוצות אלו וגם אפשרויות מתקדמות אחרות, בקרו בתיעוד של פונקציית IBM Circuit.

במדריך זה, נגדיר את default_precision, optimization_level: 3 ו-mitigation_level: 3, אשר יפעילו gate twirling ו-Zero Noise Extrapolation (ZNE) באמצעות Probabilistic Error Amplification (PEA) בנוסף להגדרות ברירת המחדל ברמה 1.

options = {
"default_precision": 0.011,
"optimization_level": 3,
"mitigation_level": 3,
}

עם הקלטים שצוינו, נשלח את העבודה לפונקציית IBM Circuit לאופטימיזציה והרצה.

job = function.run(backend_name=backend_name, pubs=pubs, options=options)

שלב 4: עיבוד לאחר ביצוע והחזרת תוצאה בפורמט קלאסי רצוי

  • קלט: תוצאות מפונקציית IBM Circuit
  • פלט: מגנטיות גלובלית

חישוב המגנטיות הגלובלית

התוצאה מהרצת הפונקציה היא באותו פורמט כמו Estimator.

result = job.result()[0]

אנו משיגים את ערכי התוחלת המופחתים והלא-מופחתים מתוצאה זו. ערכי תוחלת אלו מייצגים את המגנטיות החד-אתרית לאורך כיוון z^\hat{z}. אנו ממצעים אותם כדי להגיע למגנטיות הגלובלית ולהשוות לערך האידיאלי של 1.0 עבור מקרה בעיה זה.

mitigated_expvals = result.data.evs
magnetization_mitigated = mean(mitigated_expvals)

print("mitigated:", magnetization_mitigated)

unmitigated_expvals = [
result.data.evs_extrapolated[i][0][1] for i in range(num_qubits)
]
magnetization_unmitigated = mean(unmitigated_expvals)

print("unmitigated:", magnetization_unmitigated)
mitigated: 0.9749883476088692
unmitigated: 0.7832977198447583

סקר מדריך

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

קישור לסקר