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

קלטים ופלטים של Executor

גרסאות חבילות

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

qiskit[all]~=2.4.0
qiskit-ibm-runtime~=0.46.1
samplomatic~=0.18.0
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-ibm-runtime samplomatic

ה-primitive של Executor הוא חלק ממודל ההרצה המכוונת, שמספק גמישות רבה יותר בהתאמה אישית של תהליך עבודת הפחתת שגיאות.

הקלטים והפלטים של ה-primitive של Executor שונים מאוד מאלו של ה-primitives של Sampler ו-Estimator. לדוגמה, במקום לקבל רשימת PUBs כקלט, Executor מקבל QuantumProgram, שמכיל רשימת אובייקטי QuantumProgramItem. מחלקות מכילות אלה נותנות לך גמישות רבה יותר מ-PUB, שהוא מבנה נתונים tuple פשוט.

הפלט של Executor הוא QuantumProgramResult, שהוא iterable ומכיל אלמנט אחד לכל QuantumProgramItem קלט.

קלטים: תוכניות קוונטיות

כפי שצוין קודם, הקלט ל-primitive של Executor הוא QuantumProgram, שהוא iterable של אובייקטי QuantumProgramItem. אובייקטים אלה יכולים להיות משני סוגים:

  • CircuitItem, שבדרך כלל מאחסן מעגל וערכי הפרמטרים שלו (אם יש).
  • SamplexItem, שבדרך כלל מאחסן את הבאים:
    • מעגל template
    • אובייקט samplex, שמשמש לייצור סדרות פרמטרים אקראיות בזמן ריצה (לדוגמה לביצוע twirling או הזרקת רעש)
    • ארגומנטים עבור ה-samplex, שעשויים לכלול ערכי פרמטרים עבור המעגל המקורי

כל אחד מהפריטים הללו מייצג משימה שונה שעל Executor לבצע.

לפני שמתחילים

חלק מדוגמאות הקוד בדף זה משתמשות ב-samplex, שהוא חלק מחבילת Samplomatic. לכן, לפני הרצת בלוקי קוד אלה, חייבים להתקין את Samplomatic, כפי שמוצג בבלוק הקוד הבא. למידע נוסף, ראו את תיעוד Samplomatic.

pip install samplomatic

# For visualization support, include the visualization dependencies.
# pip install samplomatic[vis]

דוגמה: יצירת QuantumProgram עם שתי משימות שונות

ראשית אתחל את התוכנית הקוונטית שלך, ואז הוסף פריטי תוכנית אליה באמצעות append_circuit_item או append_samplex_item (אם יש samplex), כפי שמוצג בדוגמאות הבאות.

התא הבא מאתחל QuantumProgram ומציין שצריך להריץ 1024 shots עבור כל תצורה של כל פריט בתוכנית.

הערה

בשונה מ-Sampler, QuantumProgram מקבל רק ערך shot בודד. אם רוצים ערך shot שונה, צריך QuantumProgram נפרד, שיהיה עבודה נפרדת.

from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime.quantum_program import QuantumProgram
from qiskit_ibm_runtime import Executor, QiskitRuntimeService
from qiskit.circuit import Parameter, QuantumCircuit
import numpy as np
from samplomatic import build
from samplomatic.transpiler import generate_boxing_pass_manager

# Initialize an empty program
program = QuantumProgram(shots=1024)

# Initialize and transpile a 3-qubit quantum circuit with 2 parameters.
circuit = QuantumCircuit(3)
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.rz(Parameter("theta"), 0)
circuit.rz(Parameter("phi"), 1)

# `measure_all` adds a 3-bit classical register named "meas"
circuit.measure_all()

# Choose the least busy backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)

# Generate a preset pass manager
# This will be used to convert the abstract circuit to an
# equivalent Instruction Set Architecture (ISA) circuit.
preset_pass_manager = generate_preset_pass_manager(
backend=backend, optimization_level=0
)

# Transpile the circuit
isa_circuit = preset_pass_manager.run(circuit)

הוספת CircuitItem

לאחר מכן, הוסף את מעגל היעד, שבוצע עליו transpile לפי ה-instruction set architecture (ISA) של ה-backend, ל-QuantumProgram. מכיוון שלמעגל זה יש שני פרמטרים, עלינו גם לספק את ערכי הפרמטרים (10 סדרות בדוגמה זו). הרצת CircuitItem זה היא המשימה הראשונה שהתוכנית תבצע.

# Append the transpiled circuit and an array
# containing 10 sets of parameter values to the program
program.append_circuit_item(
isa_circuit,
circuit_arguments=np.random.rand(
10, 2
), # 10 sets of parameter values and 2 parameters
)

הוספת SamplexItem

פריטי Circuit מורצים ללא שום סוג של אקראיות. לעומת זאת, פריטי samplex מאפשרים לך לציין כיצד לאקראי את תוכנם. התא הבא משתמש בפונקציה generate_boxing_pass_manager() כדי לקבץ את שערי המעגל והמדידות ל-boxes ולהוסיף annotation של twirling לכל box. לאחר מכן הוא מייצר מעגל template וזוג samplex באמצעות הפונקציה build().

הרצת SamplexItem זה היא המשימה השנייה שהתוכנית תבצע.

ראו את תיעוד ה-API של Samplomatic לפרטים מלאים על samplex וארגומנטיו. ראו את מדריך ה-Transpiler של Samplomatic למידע על שימוש בפונקציה generate_boxing_pass_manager().

# Transpile the circuit, additionally grouping gates and measurements into annotated boxes
preset_pass_manager = generate_preset_pass_manager(
backend=backend, optimization_level=0
)

# Use the boxing pass manager to group gates
# and measurements into boxes and add
# a`Twirl` annotation.
preset_pass_manager.post_scheduling = generate_boxing_pass_manager(
# Add gate twirling
enable_gates=True,
# Add measurement twirling
enable_measures=True,
)
boxed_circuit = preset_pass_manager.run(circuit)

# Build the template circuit and the samplex. The template circuit has parametric gates
# without fixed values and the samplex randomly generates the parameter
# values on the server side at runtime to perform twirling.
template_circuit, samplex = build(boxed_circuit)

# Determine what arguments are required by the samplex.
# Input the arguments in samplex_arguments.
print(samplex.inputs())
TensorInterface(<
- 'parameter_values' <float64[2]>: Input parameter values to use during sampling.
>)
# Append the template circuit and samplex as a samplex item
program.append_samplex_item(
template_circuit,
samplex=samplex,
samplex_arguments={
# the arguments required by the samplex.sample method
"parameter_values": np.random.rand(10, 2),
},
shape=(28, 10), # 28 randomizations and 10 sets of parameter values
)
# Initialize an Executor with the default options
executor = Executor(mode=backend)

# Submit the job
job = executor.run(program)

# Retrieve the result
result = job.result()

פלטים

הפלט של Executor הוא QuantumProgramResult, שהוא iterable. הוא מכיל ערך אחד לכל QuantumProgramItem קלט באותו סדר כמו פריטי הקלט. כל אחד מפריטי הפלט הללו הוא מילון שבו המפתחות הם מחרוזות המתאימות לשמות הרגיסטרים הקלאסיים במעגלי הקלט (בין היתר), כך שכבר אין צורך לזכור שמות אלה כפי שהיה צריך עם פלט Sampler. ערכי המילון הם מסוג np.ndarray.

התוצאה עבור הדוגמה הקודמת מכילה את הפריטים הבאים:

תוצאת CircuitItem

הפריט הראשון מכיל את תוצאות הרצת המשימה הראשונה (CircuitItem) בתוכנית. הוא מכיל מפתח בודד, meas, שהוא שם הרגיסטר הקלאסי במעגל הקלט. ערך מפתח זה ממפה ל-np.ndarray בצורה (parameter sets, shots, register bits), שהיא (10, 1024, 3) בדוגמה לעיל.

הקוד הבא ממחיש כיצד לגשת למידע זה:

# Access the results of the classical register of task #0, a CircuitItem
result_0 = result[0]["meas"]
print(f"Result shape: {result_0.shape}")
Result shape: (10, 1024, 3)

תוצאת SamplexItem

הפריט השני מכיל את תוצאות הרצת המשימה השנייה (SamplexItem) בתוכנית. פריט זה מכיל מספר מפתחות. המפתח meas, שהוא שם הרגיסטר הקלאסי של מעגל הקלט, ממפה למערך תוצאות של אותו רגיסטר. למערך זה יש צורה (randomizations, parameter sets, shots, classical bits), או (28, 10, 1024, 3) בדוגמה זו. בנוסף, הפלט מכיל מפתח measurement_flips.meas, שהוא תיקוני היפוך סיביות לביטול ה-measurement twirling עבור רגיסטר ה-meas. צורת פלט זו תהיה (28, 10, 1, 3) בדוגמה שלנו מכיוון שנדרש רק shot אחד לביצוע ההיפוך.

# Access the results of the classical register of task #1
result_1 = result[1]["meas"]
print(f"Result shape: {result_1.shape}")

# Access the bit-flip corrections
flips_1 = result[1]["measurement_flips.meas"]
print(f"Bit-flip corrections shape: {flips_1.shape}")

# Undo the bit flips via classical XOR
unflipped_result_1 = result_1 ^ flips_1
Result shape: (28, 10, 1024, 3)
Bit-flip corrections shape: (28, 10, 1, 3)

השלבים הבאים

המלצות