תחילת העבודה עם חיתוך מעגלים באמצעות חיתוכי Wire
גרסאות חבילות
הקוד בדף זה פותח עם הדרישות הבאות. מומלץ להשתמש בגרסאות אלה או בגרסאות חדשות יותר.
qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
qiskit-aer~=0.17
qiskit-addon-cutting~=0.10.0
מדריך זה מדגים דוגמת עבודה של חיתוכי Wire עם חבילת qiskit-addon-cutting. הוא מכסה בנייה מחדש של ערכי ההציפייה של מעגל בן שבעה Qubit-ים באמצעות חיתוך Wire.
חיתוך Wire מיוצג בחבילה זו כהוראת Move דו-Qubit, שמוגדרת כאיפוס של ה-Qubit השני שעליו פועלת ההוראה, ולאחר מכן חילוף של שני ה-Qubit-ים. פעולה זו שקולה להעברת המצב של ה-Qubit הראשון אל ה-Qubit השני, תוך השלכת המצב הנכנס של ה-Qubit השני בו-זמנית.
החבילה מתוכננת להיות עקבית עם האופן שבו חייבים לטפל בחיתוכי Wire בעת פעולה על Qubit-ים פיזיים. לדוגמה, חיתוך Wire עשוי לקחת את המצב של Qubit פיזי ולהמשיך אותו כ-Qubit פיזי לאח ר החיתוך. אפשר לחשוב על "חיתוך הוראות" כמסגרת אחידה לשקול גם חיתוכי Wire וגם חיתוכי Gate באותה פורמליזם (מכיוון שחיתוך Wire הוא פשוט הוראת Move חתוכה). שימוש במסגרת זו לחיתוך Wire מאפשר גם שימוש חוזר ב-Qubit-ים, המוסבר בחלק על חיתוך Wire ידני.
הוראת CutWire החד-Qubit משמשת כממשק מופשט ופשוט יותר לעבודה עם חיתוכי Wire. היא מאפשרת לציין היכן במעגל צריך לחתוך wire ברמה גבוהה ולאפשר לתוסף חיתוך המעגלים להכניס הוראות Move מתאימות במקומך.
הדוגמה הבאה מדגימה בנייה מחדש של ערך ההציפייה לאחר חיתוך Wire. תיצור מעגל עם מספר Gate-ים לא-מקומיים ותגדיר observable-ים לאמידה.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-addon-cutting qiskit-aer qiskit-ibm-runtime
import numpy as np
from qiskit import QuantumCircuit
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.quantum_info import SparsePauliOp
from qiskit_ibm_runtime.fake_provider import FakeManilaV2
from qiskit_ibm_runtime import SamplerV2, Batch
from qiskit_aer.primitives import EstimatorV2
from qiskit_addon_cutting.instructions import Move, CutWire
from qiskit_addon_cutting import (
partition_problem,
generate_cutting_experiments,
cut_wires,
expand_observables,
reconstruct_expectation_values,
)
qc_0 = QuantumCircuit(7)
for i in range(7):
qc_0.rx(np.pi / 4, i)
qc_0.cx(0, 3)
qc_0.cx(1, 3)
qc_0.cx(2, 3)
qc_0.cx(3, 4)
qc_0.cx(3, 5)
qc_0.cx(3, 6)
qc_0.cx(0, 3)
qc_0.cx(1, 3)
qc_0.cx(2, 3)
# Define observable
observable = SparsePauliOp(["ZIIIIII", "IIIZIII", "IIIIIIZ"])
# Draw circuit
qc_0.draw("mpl")
חיתוך Wire באמצעות הוראת CutWire ברמה גבוהה
בשלב הבא, בצע חיתוכי Wire באמצעות הוראת CutWire החד-Qubit על Qubit . לאחר שתת-הניסויים מוכנים לביצוע, השתמש בפונקציה cut_wires() כדי להמיר הוראות CutWire להוראות Move על Qubit-ים שהוקצו לאחרונה.
qc_1 = QuantumCircuit(7)
for i in range(7):
qc_1.rx(np.pi / 4, i)
qc_1.cx(0, 3)
qc_1.cx(1, 3)
qc_1.cx(2, 3)
qc_1.append(CutWire(), [3])
qc_1.cx(3, 4)
qc_1.cx(3, 5)
qc_1.cx(3, 6)
qc_1.append(CutWire(), [3])
qc_1.cx(0, 3)
qc_1.cx(1, 3)
qc_1.cx(2, 3)
qc_1.draw("mpl")
כאשר מעגל מורחב דרך חיתוך wire אחד או יותר, יש לעדכן את ה-observable כדי להתחשב ב-Qubit-ים הנוספים שמוכנסים. לחבילת qiskit-addon-cutting יש פונקציית עזר expand_observables(), שמקבלת אובייקטי PauliList ואת המעגלים המקורי והמורחב כארגומנטים, ומחזירה PauliList חדש.
ה-PauliList המוחזר לא יכיל מידע על מקדמי ה-observable המקורי, אך ניתן להתעלם מהם עד לשלב בנייה מחדש של ערך ההציפייה הסופי.
# Transform CutWire instructions to Move instructions
qc_2 = cut_wires(qc_1)
# Expand the observable to match the new circuit size
expanded_observable = expand_observables(observable.paulis, qc_0, qc_2)
print(f"Expanded Observable: {expanded_observable}")
qc_2.draw("mpl")
Expanded Observable: ['ZIIIIIIII', 'IIIZIIIII', 'IIIIIIIIZ']