Input dan output Executor
Versi pakej
Kod di halaman ini dibangunkan menggunakan keperluan berikut. Kami syorkan menggunakan versi ini atau yang lebih baru.
qiskit[all]~=2.6.1
qiskit-ibm-runtime~=0.50.0
samplomatic~=0.21.0
Primitif Executor adalah sebahagian daripada model pelaksanaan berarah, yang memberikan lebih fleksibiliti apabila menyesuaikan aliran kerja pengurangan ralat.
Input dan output primitif Executor sangat berbeza daripada primitif Sampler dan Estimator. Sebagai contoh, daripada mengambil senarai PUB sebagai input, Executor mengambil QuantumProgram, yang mengandungi senarai objek QuantumProgramItem. Kelas bekas ini memberi anda lebih fleksibiliti berbanding PUB, yang merupakan struktur data tupel mudah.
Output Executor adalah QuantumProgramResult, yang merupakan iterable dan mengandungi satu elemen untuk setiap QuantumProgramItem input.
Input: Program kuantum
Seperti yang dinyatakan sebelumnya, input kepada primitif Executor adalah QuantumProgram, yang merupakan iterable objek
QuantumProgramItem. Objek-objek ini boleh terdiri daripada dua jenis:
CircuitItem, yang biasanya menyimpan Circuit dan nilai parameternya (jika ada).SamplexItem, yang biasanya menyimpan yang berikut:- Circuit templat
- Objek samplex, yang digunakan untuk menjana set parameter rawak pada masa jalan (misalnya untuk melakukan twirling atau menyuntik hingar)
- Argumen untuk samplex, yang mungkin termasuk nilai parameter untuk Circuit asal
Setiap item ini mewakili tugas berbeza yang perlu dilaksanakan oleh Executor.
Sebelum anda mulakan
Sesetengah contoh kod di halaman ini menggunakan samplex, yang merupakan sebahagian daripada pakej Samplomatic. Oleh itu, sebelum menjalankan blok kod tersebut, anda mesti memasang Samplomatic, seperti yang ditunjukkan dalam blok kod berikut. Untuk maklumat lanjut, lihat dokumentasi Samplomatic.
pip install samplomatic
# For visualization support, include the visualization dependencies.
# pip install samplomatic[vis]
Contoh: Cipta QuantumProgram dengan dua tugas berbeza
Pertama mulakan program kuantum anda, kemudian tambahkan item program kepadanya menggunakan sama ada append_circuit_item atau append_samplex_item (jika samplex hadir), seperti yang ditunjukkan dalam contoh-contoh berikut.
Sel berikut memulakan QuantumProgram dan menentukan bahawa ia harus menjalankan 1024 tembakan untuk setiap konfigurasi setiap item dalam program.
Tidak seperti Sampler, QuantumProgram hanya menerima satu nilai tembakan. Jika anda mahukan nilai tembakan yang berbeza, anda memerlukan QuantumProgram berasingan, yang akan menjadi kerja berasingan.
# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util
_needed = {"numpy": "numpy", "qiskit": "qiskit", "qiskit_ibm_runtime": "qiskit-ibm-runtime", "samplomatic": "samplomatic"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
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)
Tambah CircuitItem
Seterusnya, tambahkan Circuit sasaran, yang telah ditranspil mengikut seni bina set arahan (ISA) Backend, ke QuantumProgram. Oleh kerana Circuit ini mempunyai dua parameter, kita juga perlu menyediakan nilai parameter (10 set dalam contoh ini). Menjalankan CircuitItem ini adalah tugas pertama yang akan dilakukan oleh program.
# 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
)
Tambah SamplexItem
Item Circuit dilaksanakan tanpa sebarang rawakan. Sebaliknya, item samplex membolehkan anda menentukan cara merawakkan kandungannya. Sel berikut menggunakan fungsi generate_boxing_pass_manager() untuk mengumpulkan gate dan ukuran Circuit ke dalam kotak dan menambahkan anotasi twirling ke setiap kotak. Ia kemudian menjana Circuit templat dan pasangan samplex menggunakan fungsi build().
Menjalankan SamplexItem ini adalah tugas kedua yang akan dilakukan oleh program.
Lihat dokumentasi API Samplomatic untuk butiran penuh tentang samplex dan argumennya. Lihat Panduan Transpiler Samplomatic untuk maklumat tentang penggunaan fungsi 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()
Output
Output Executor adalah QuantumProgramResult, yang merupakan iterable. Ia mengandungi satu entri per QuantumProgramItem input dalam susunan yang sama seperti item input. Setiap item output ini adalah kamus di mana kuncinya adalah rentetan yang sepadan dengan nama daftar klasik dalam Circuit input (antara lain), jadi anda tidak perlu lagi menghafal nama-nama ini seperti yang anda lakukan dengan output Sampler. Nilai kamus adalah dari jenis np.ndarray.
Keputusan untuk contoh sebelumnya mengandungi item-item ini:
Keputusan CircuitItem
Item pertama mengandungi hasil daripada menjalankan tugas pertama (CircuitItem) dalam program. Ia mengandungi satu kunci tunggal, meas, iaitu nama daftar klasik dalam Circuit input. Nilai kunci ini dipetakan kepada np.ndarray berbentuk (parameter sets, shots, register bits), iaitu (10, 1024, 3) untuk contoh di atas.
Kod berikut menggambarkan cara mengakses maklumat ini:
# 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)
Paksi paling kanan bagi result_0 merentasi bit klasik dalam susunan little-endian. Jadi, indeks 0 menyimpan hasil bit klasik 0, iaitu bit paling kurang bererti.
Keputusan SamplexItem
Item kedua mengandungi hasil daripada menjalankan tugas kedua (SamplexItem) dalam program. Item ini mengandungi beberapa kunci. Kunci meas, iaitu nama daftar klasik litar input, dipetakan kepada tatasusunan hasil bagi daftar tersebut. Tatasusunan ini mempunyai bentuk (randomizations, parameter sets, shots, classical bits), atau (28, 10, 1024, 3) dalam contoh ini.
Selain itu, output mengandungi kunci measurement_flips.meas, iaitu pembetulan bit-flip untuk membatalkan twirling pengukuran bagi daftar meas. Bentuk output ini akan menjadi (28, 10, 1, 3) untuk contoh kita kerana hanya satu tembakan diperlukan untuk melakukan bit-flip.
Perhatikan bahawa paksi paling kanan bagi result_1 merentasi bit klasik dalam susunan little-endian.
# 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)
Lihat execution spans
Satu panggilan Executor.run() menghantar satu job. Namun, di sisi pelayan, perkhidmatan tidak semestinya menjalankan setiap konfigurasi program kuantum pada masa yang sama. Sebaliknya, ia mengumpulkan litar terikat bagi item program ke dalam chunk, dan menjalankan satu chunk pada satu masa pada QPU. Anda tidak perlu memisahkan program anda atau menghantar job tambahan; pengchunkan berlaku secara automatik dalam satu job tersebut. Atribut metadata keputusan mengandungi maklumat masa tentang chunk ini dalam result.metadata.chunk_timing. Cap masa ini ialah masa mula dan henti sebenar setiap chunk pada QPU. Anda boleh menggunakan maklumat ini untuk melihat bila data tertentu dikumpulkan pada QPU, untuk memahami cara Executor mengagihkan kerja, atau untuk mendiagnosis isu prestasi.
chunk_timing ialah senarai yang mengandungi satu ChunkSpan bagi setiap chunk yang dilaksanakan. Setiap ChunkSpan mempunyai atribut berikut:
-
startdanstop: Cap masa UTC apabila chunk mula dan berhenti dilaksanakan pada QPU. -
parts: Senarai objekChunkPartyang menerangkan item program mana yang menyumbang kepada chunk. SetiapChunkPartmengandungi yang berikut:-
idx_item: Indeks item program, mengikut turutan item ditambahkan padaQuantumProgram. -
size: Bilangan konfigurasi (elemen bentuk item) daripada item tersebut yang dilaksanakan dalam chunk ini. Contohnya,SamplexItemdalam contoh sebelumnya mempunyai bentuk(28, 10), jadi ia mempunyai 280 konfigurasi keseluruhannya.
-
Kod berikut mencetak tempoh setiap chunk dan kandungan setiap chunk bagi job yang dihantar sebelum ini:
for idx, span in enumerate(result.metadata.chunk_timing):
duration = (span.stop - span.start).total_seconds()
print(f"Chunk {idx}: {span.start} to {span.stop} ({duration:.3f} s)")
for part in span.parts:
print(f" Item {part.idx_item}: {part.size} configurations")
Chunk 0: 2026-11-06 01:47:46.009718+00:00 to 2026-11-06 01:49:05.577720+00:00 (79.568 s)
Item 0: 10 configurations
Item 1: 280 configurations
Sifat QuantumProgramResult.timing membungkus senarai yang sama dalam objek ChunkTiming, yang turut melaporkan maklumat global tentang koleksi chunk:
timing = result.timing
print("Number of chunks:", len(timing))
print(" Start of the first chunk:", timing.start)
print(" End of the last chunk:", timing.stop)
print(" Total duration (s):", timing.duration)
Number of chunks: 1
Start of the first chunk: 2026-11-06 01:47:46.009718+00:00
End of the last chunk: 2026-11-06 01:49:05.577720+00:00
Total duration (s): 79.568002
Visualisasikan execution spans
Gunakan fungsi draw_chunk_timings untuk memvisualisasikan masa chunk pada plot bar interaktif. Paksi-x ialah masa, dan setiap chunk dilukis sebagai segmen mendatar yang merangkumi masa mula dan hentinya. Paksi-y menunjukkan bilangan kumulatif konfigurasi yang selesai (atau peratusan daripada jumlah beban kerja, jika anda menetapkan normalize_y=True). Layangkan tetikus pada segmen untuk melihat cap masa, tempoh, dan bahagian chunk tersebut.
Fungsi ini mengembalikan rajah plotly, yang boleh anda paparkan terus, simpan ke fail, atau kedua-duanya. Ia menerima sama ada senarai chunk_timing atau objek ChunkTiming. Anda boleh menghantar beberapa daripadanya, contohnya daripada job yang berbeza, untuk melukisnya pada plot yang sama. Tetapkan common_start=True untuk menyelaraskannya pada masa mula bersama bagi perbandingan.
draw_chunk_timings memerlukan plotly. Anda boleh memasangnya dengan menjalankan pip install plotly.
Visualisasi mungkin menunjukkan jurang antara pelaksanaan chunk. Semua job yang dihantar kepada QPU sebenar melalui sedikit prapemprosesan klasik, seperti penterjemahan kepada denyut yang boleh dihantar ke perkakasan. Oleh sebab prapemprosesan ini boleh dilakukan secara selari, perkhidmatan mengeluarkan beberapa job daripada baris gilir dan memulakannya serentak. Namun, QPU hanya boleh memproses satu unit kerja pada satu masa. Oleh itu, jika sesuatu job menjana beberapa chunk, chunknya mungkin diselang-seli dengan chunk job pengguna lain, dan setiap chunk mungkin perlu menunggu gilirannya pada QPU. Inilah sebabnya jurang boleh muncul antara chunk.
from qiskit_ibm_runtime.visualization import draw_chunk_timings
fig = draw_chunk_timings(result.timing, names="Executor job")
# Alternatively, call the `draw()` method of the ChunkTiming object
# fig = result.timing.draw()
# Uncomment the following line to display the figure
# fig.show(renderer="notebook")
# Save to a file
# fig.write_html("chunk_timings.html")
Langkah seterusnya
- Terokai contoh yang menggunakan Executor.
- Ketahui tentang model pelaksanaan berarah.
- Fahami penyiaran Executor.