אומדן פאזה קוונטי עם הפונקציות של Q-CTRL ב-Qiskit
הערכת שימוש: 40 שניות על מעבד Heron r2. (הערה: זוהי אומדן בלבד. זמן הריצה בפועל עשוי להשתנות.)
רקע
אומדן פאזה קוונטי (QPE) הוא אלגוריתם יסודי בחישוב קוונטי המהווה את הבסיס ליישומים חשובים רבים כגון אלגוריתם שור, הערכת אנרגיית מצב היסוד בכימיה קוונטית ובעיות ערכים עצמיים. QPE מעריך את הפאזה המקושרת למצב עצמי של אופרטור אוניטרי, המקודדת ביחס
וקובע אותה לדיוק של באמצעות קיוביטי ספירה [1]. על ידי הכנת קיוביטים אלה בסופרפוזיציה, הפעלת חזקות מבוקרות של , ולאחר מכן שימוש בהתמרת פורייה קוונטית הפוכה (QFT) כדי לח לץ את הפאזה לתוצאות מדידה מקודדות בינארית, QPE מייצר התפלגות הסתברות עם שיא בסדרות ביטים ששברים בינאריים שלהן מקרבים את . במקרה האידיאלי, תוצאת המדידה הסבירה ביותר מתאימה ישירות להרחבה בינארית של הפאזה, בעוד שההסתברות לתוצאות אחרות יורדת במהירות עם מספר קיוביטי הספירה. עם זאת, הרצת מעגלי QPE עמוקים על חומרה מציגה אתגרים: המספר הגדול של קיוביטים ופעולות שזירה הופך את האלגוריתם לרגיש מאוד לדה-קוהרנטיות ולשגיאות שערים. התוצאה היא התפלגויות מורחבות ומוסטות של סדרות ביטים, המסתירות את הפאזה העצמית האמיתית. כתוצאה מכך, סדרת הביטים עם ההסתברות הגבוהה ביותר עשויה לא להתאים יותר להרחבה הבינארית הנכונה של .
במדריך זה, אנחנו מציגים מימוש של אלגוריתם QPE באמצעות כלי דיכוי שגיאות וניהול ביצועים של Fire Opal מבית Q-CTRL, המוצעים כפונקציית Qiskit (ראה את תיעוד Fire Opal). Fire Opal מיישם אוטומטית אופטימיזציות מתקדמות, לרבות ניתוק דינמי, שיפורי פריסת קיוביטים וטכניקות דיכוי שגיאות, וכתוצאה מכך תוצאות בעלות נאמנות גבוהה יותר. שיפורים אלה מקרבים את התפלגויות סדרות הביטים בחומרה לאלה המתקבלות בסימולציות חסרות רעש, כך שתוכלו לזהות באופן אמין את הפאזה העצמית הנכונה גם תחת השפעות הרעש.
דרישות
לפני התחלת מדריך זה, ודאו שמותקנים לכם הרכיבים הבאים:
- Qiskit SDK גרסה 1.4 ומעלה, עם תמיכה בויזואליזציה
- Qiskit Runtime גרסה 0.40 ומעלה (
pip install qiskit-ibm-runtime) - Qiskit Functions Catalog גרסה 0.9.0 (
pip install qiskit-ibm-catalog) - Fire Opal SDK גרסה 9.0.2 ומעלה (
pip install fire-opal) - Q-CTRL Visualizer גרסה 8.0.2 ומעלה (
pip install qctrl-visualizer)
הגדרה
ראשית, בצעו אימות באמצעות מפתח API של IBM Quantum שלכם. לאחר מכן, בחרו את פונקציית Qiskit כדלקמן. (קוד זה מניח שכבר שמרתם את החשבון שלכם לסביבה המקומית שלכם.)
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qctrlvisualizer qiskit qiskit-aer qiskit-ibm-catalog qiskit-ibm-runtime
from qiskit import QuantumCircuit
import numpy as np
import matplotlib.pyplot as plt
import qiskit
from qiskit import qasm2
from qiskit_aer import AerSimulator
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import SamplerV2 as Sampler
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
import qctrlvisualizer as qv
from qiskit_ibm_catalog import QiskitFunctionsCatalog
plt.style.use(qv.get_qctrl_style())
catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")
# Access Function
perf_mgmt = catalog.load("q-ctrl/performance-management")
שלב 1: מיפוי קלטים קלאסיים לבעיה קוונטית
במדריך זה, אנחנו ממחישים את QPE כדי לשחזר את הפאזה העצמית של אוניטרי ידוע של קיוביט יחיד. האוניטרי שאת הפאזה שלו אנחנו רוצים להעריך הוא שער הפאזה של קיוביט יחיד המופעל על קיוביט היעד:
אנחנו מכינים את המצב העצמי שלו . מכיוון ש- הוא וקטור עצמי של עם ערך עצמי , הפאזה העצמית שיש להעריך היא:
אנחנו מגדירים , כך שהפאזה האמיתית היא . מעגל QPE מיישם את החזקות המבוקרות על ידי הפעלת סיבובי פאזה מבוקרים עם זוויות , לאחר מכן מיישם את ה-QFT ההפוך על רגיסטר הספירה ומודד אותו. סדרות הביטים המתקבלות מתרכזות סביב הייצוג הבינארי של .
המעגל משתמש ב- קיוביטי ספירה (כדי להגדיר את דיוק האומדן) בתוספת קיוביט יעד אחד. נתחיל בהגדרת אבני הבני ין הנדרשות למימוש QPE: התמרת פורייה קוונטית (QFT) וההפוכה שלה, פונקציות עזר למיפוי בין שברים עשרוניים ובינאריים של הפאזה העצמית, ועוזרים לנרמול ספירות גולמיות להסתברויות לצורך השוואת תוצאות סימולציה וחומרה.
def inverse_quantum_fourier_transform(quantum_circuit, number_of_qubits):
"""
Apply an inverse Quantum Fourier Transform the first `number_of_qubits` qubits in the
`quantum_circuit`.
"""
for qubit in range(number_of_qubits // 2):
quantum_circuit.swap(qubit, number_of_qubits - qubit - 1)
for j in range(number_of_qubits):
for m in range(j):
quantum_circuit.cp(-np.pi / float(2 ** (j - m)), m, j)
quantum_circuit.h(j)
return quantum_circuit
def bitstring_count_to_probabilities(data, shot_count):
"""
This function turns an unsorted dictionary of bitstring counts into a sorted dictionary
of probabilities.
"""
# Turn the bitstring counts into probabilities.
probabilities = {
bitstring: bitstring_count / shot_count
for bitstring, bitstring_count in data.items()
}
sorted_probabilities = dict(
sorted(probabilities.items(), key=lambda x: x[1], reverse=True)
)
return sorted_probabilities
שלב 2: אופטימיזציה של הבעיה לביצוע על חומרה קוונטית
אנחנו בונים את מעגל QPE על ידי הכנת קיוביטי הספירה בסופרפוזיציה, הפעלת סיבובי פאזה מבוקרים כדי לקודד את הפאזה העצמית של היעד, וסיום עם QFT הפוך לפני המדידה.
def quantum_phase_estimation_benchmark_circuit(
number_of_counting_qubits, phase
):
"""
Create the circuit for quantum phase estimation.
Parameters
----------
number_of_counting_qubits : The number of qubits in the circuit.
phase : The desired phase.
Returns
-------
QuantumCircuit
The quantum phase estimation circuit for `number_of_counting_qubits` qubits.
"""
qc = QuantumCircuit(
number_of_counting_qubits + 1, number_of_counting_qubits
)
target = number_of_counting_qubits
# |1> eigenstate for the single-qubit phase gate
qc.x(target)
# Hadamards on counting register
for q in range(number_of_counting_qubits):
qc.h(q)
# ONE controlled phase per counting qubit: cp(phase * 2**k)
for k in range(number_of_counting_qubits):
qc.cp(phase * (1 << k), k, target)
qc.barrier()
# Inverse QFT on counting register
inverse_quantum_fourier_transform(qc, number_of_counting_qubits)
qc.barrier()
for q in range(number_of_counting_qubits):
qc.measure(q, q)
return qc