Berpindah daripada Sampler kepada Executor
Panduan ini menerangkan cara memindahkan beban kerja pensampelan kuantum dari primitif IBM Quantum® Sampler kepada primitif Executor.
Primitif Executor adalah sebahagian daripada model pelaksanaan terarah. Semua komponen dalam model pelaksanaan terarah kini dalam beta dan mungkin tidak stabil. Kamu dijemput untuk mengujinya dan memberi maklum balas dengan membuka isu dalam repositori GitHub Samplomatic atau qiskit-ibm-runtime.
Patutkah kamu berpindah?
Bukan semua orang patut berpindah daripada Sampler kepada Executor. Terdapat banyak perbezaan antara primitif ini, tetapi panduan berikut boleh membantu kamu memutuskan sama ada untuk berpindah:
Berpindah kepada Executor jika kamu seorang saintis maklumat kuantum yang menjalankan eksperimen berskala utiliti dan memerlukan kawalan yang terperinci dan boleh dihasilkan semula terhadap teknik seperti Pauli twirling, pembelajaran dan suntikan model hingar, dan perubahan asas — atau yang memerlukan salah satu keupayaan tambahan yang disediakan oleh Executor.
Teruskan menggunakan Sampler jika kamu mahukan antara muka yang mudah, tahap tinggi dan mahu primitif mengurus penindasan dan mitigasi ralat untuk kamu.
Batasan dan peringatan
Kerana Executor dan model pelaksanaan terarah masih dalam beta, ambil perhatian yang berikut sebelum kamu memutuskan untuk berpindah:
-
Belum ada sokongan simulator: Tidak seperti Sampler, yang mempunyai pelaksanaan
AerSamplerdalamqiskit-aeruntuk simulasi tempatan, kini tiada backend simulator untuk Executor. Sokongan simulator dijangka tiba tidak lama lagi. Sementara itu, kamu masih boleh memeriksa dan mensampel circuit templat secara tempatan untuk mengesahkan alur kerja kamu sebelum menyerahkannya ke perkakasan. -
Panduan ini hanya meliputi Sampler, bukan Estimator. Berpindah dari Estimator kepada Executor adalah jauh lebih rumit daripada berpindah dari Sampler kerana Estimator mengira nilai jangkaan bukannya mengembalikan sampel mentah. Menghasilkan semula tingkah laku Estimator dengan Executor memerlukan pemprosesan pasca tambahan. Fungsi utiliti untuk membantu berpindah dari Estimator kepada Executor masih dalam pembangunan, jadi panduan ini sengaja hanya menerangkan alur kerja Sampler.
Perbezaan utama antara Executor dan Sampler
Sampler dan Executor kedua-duanya mensampel daftar output circuit kuantum, tetapi mereka mensasarkan pengguna yang berbeza:
-
Sampler ialah abstraksi peringkat tinggi. Ia mempunyai ciri-ciri berikut:
-
Ia mempunyai penindasan ralat terbina dalam (dynamical decoupling dan twirling).
-
Ia membuat keputusan tersirat untuk kamu.
-
Ia direka supaya pembangun algoritma boleh fokus kepada inovasi bukannya penukaran data.
-
-
Executor adalah sebahagian daripada model pelaksanaan terarah. Ia berbeza daripada Sampler dalam banyak cara dan mempunyai ciri-ciri berikut:
-
Ia tiada penindasan atau mitigasi ralat terbina dalam. Sebaliknya, kamu menangkap niat reka bentuk kamu di sisi klien (dengan menggunakan anotasi circuit dan samplex), dan penjanaan varian circuit yang mahal dialihkan ke sisi pelayan.
-
Ia tidak membuat keputusan tersirat. Ia mengikut arahan kamu dengan tepat, memberikan kawalan dan ketelusan penuh.
-
Executor dan Samplomatic bersama-sama mendedahkan keupayaan tambahan yang Sampler tidak tawarkan, termasuk (tetapi tidak terhad kepada) yang berikut:
- Lebih banyak kumpulan twirling: Samplomatic membolehkan kamu memilih kumpulan twirling mana yang hendak digunakan
bagi setiap box, bukannya terhad kepada strategi tunggal yang Sampler gunakan untuk kamu. Ia juga menyokong kumpulan twirling selain Pauli, seperti kumpulan twirling
"local_c1". - Pengukuran kernel dan terklasifikasi bersama: Menetapkan
QuantumProgram.meas_level = "both"(ditambah dalamqiskit-ibm-runtimev0.48.0) meminta supaya kedua-dua pengukuran terklasifikasi dan kernel hadir dalam hasil, bukannya memilih satu jenis pengukuran bagi setiap kerja. - Twirling untuk circuit dengan gate pecahan: Executor boleh menggunakan twirling pada circuit yang mengandungi gate pecahan.
- Mitigasi ralat yang terperinci dan boleh digubah: Contohnya, memilih lapisan circuit mana yang hendak dimitigasi dan melaraskan kadar hingar yang disuntik ke dalam circuit.
Notes- Keupayaan baharu pada masa hadapan dijangka dikeluarkan kepada Executor dahulu dan mungkin tidak dipindahkan ke Sampler. Jika kamu bergantung kepada akses kepada ciri terkini, Executor adalah pilihan yang lebih tahan masa hadapan.
- Pakej Qiskit asas belum lagi menyediakan
kelas asas untuk primitif Executor (ia menyediakannya untuk
SamplerV2).
- Lebih banyak kumpulan twirling: Samplomatic membolehkan kamu memilih kumpulan twirling mana yang hendak digunakan
bagi setiap box, bukannya terhad kepada strategi tunggal yang Sampler gunakan untuk kamu. Ia juga menyokong kumpulan twirling selain Pauli, seperti kumpulan twirling
-
Pemetaan konsep
Jadual berikut menunjukkan bagaimana konsep Sampler dipetakan kepada Executor.
| Konsep | Sampler | Executor |
|---|---|---|
| Import | from qiskit_ibm_runtime import SamplerV2 | from qiskit_ibm_runtime import Executor |
| Input | Senarai PUB (tuple) | QuantumProgram daripada objek QuantumProgramItem |
| Circuit dan parameter | Tuple (circuit, params, shots) | program.append_circuit_item(circuit, circuit_arguments=...) |
| Twirling | TwirlingOptions | Secara eksplisit melalui kotak beranotasi dan samplex (append_samplex_item) |
| Panggilan run | sampler.run([pub, ...]) | executor.run(program) |
| Jenis hasil | PrimitiveResult daripada SamplerPubResult | QuantumProgramResult (boleh diulang) |
| Akses data | result[0].data.<register> (BitArray) | result[0]["<register>"] (np.ndarray) |
| Urus hingar | Pilihan terbina dalam | Perlu digubah secara manual (anotasi, samplex, NoiseLearnerV3) |
Gambaran keseluruhan langkah-langkah migrasi
Langkah 1. Pasang pakej yang diperlukan
Executor dan model pelaksanaan terarah memerlukan pakej samplomatic:
pip install qiskit qiskit-ibm-runtime samplomatic
# For visualization support:
# pip install samplomatic[vis]
qiskit-ibm-runtimev0.48.0 disyorkan kerana ia menambah pilihanmeas_level = "both"dan kumpulan twirlinglocal_c1.qiskit >= 2.3.0diperlukan.samplomatic >= 0.18.0diperlukan.
Langkah 2. Ubah import
Sampler:
from qiskit_ibm_runtime import SamplerV2 as Sampler
Executor:
from qiskit_ibm_runtime import Executor, QuantumProgram
Langkah 3. Gantikan tuple PUB dengan QuantumProgram
Bukannya menghantar senarai tuple (PUB), apabila menggunakan Executor, kamu membina QuantumProgram dan melampirkan item kepadanya.
QuantumProgram menerima item circuit dan item samplex:
-
append_circuit_item: MelampirkanCircuitItem, iaitu circuit dan (secara pilihan) nilai parameternya. Ia dilaksanakan sebagaimana adanya, tanpa sebarang rawakan.Gunakan ini apabila kamu hanya mahu mensampel circuit, tepat seperti Sampler lakukan dengan PUB yang tiada twirling; contohnya, apabila menyerahkan kerja pensampelan biasa, atau apabila kamu sudah memasukkan secara manual varian yang kamu mahu.
-
append_samplex_item: MelampirkansamplexItem, iaitu circuit templat ditambah samplex yang menjana set parameter rawak di sisi pelayan.Gunakan ini apabila kamu mahu kandungan circuit dirawakkan. Kes utama adalah dengan twirling (gate atau pengukuran) atau suntikan hingar. Keupayaan ini menggantikan twirling terbina dalam Sampler.
Satu QuantumProgram boleh menerima kedua-dua jenis item; setiap item yang dilampirkan dilaksanakan sebagai
tugas bebas dan menghasilkan entrinya sendiri dalam hasil. Secara umum, gunakan append_circuit_item apabila circuit kamu tidak perlu dirawakkan. Jika tidak, gunakan append_samplex_item.
Bahagian seterusnya menunjukkan setiap satu secara bergilir: circuit berparameter yang menggunakan
append_circuit_item, dan memindahkan twirling dengan menggunakan append_samplex_item.
Dalam contoh kod berikut, isa_circuit merujuk kepada circuit yang telah ditranspil untuk mematuhi Instruction Set Architecture (ISA) backend sasaran. isa_circuit ini mengandungi dua parameter.
Langkah 3a. Pindahkan circuit berparameter
Dengan Sampler, nilai parameter adalah elemen kedua tuple PUB. Dengan Executor,
hantarkannya sebagai circuit_arguments kepada append_circuit_item.
Sampler:
params = np.random.rand(10, circuit.num_parameters) # 10 parameter sets
pubs = (isa_circuit, params)
Executor
program = QuantumProgram(shots=1024)
program.append_circuit_item(
isa_circuit,
circuit_arguments=np.random.rand(10, circuit.num_parameters), # 10 sets
)
# CircuitItem result shape: (parameter_sets, shots, register_bits) -> (10, 1024, 2)
result_0 = result[0]["meas"]
Langkah 3b. Pindahkan twirling terbina dalam kepada anotasi eksplisit
Ini adalah perubahan yang paling ketara. Sampler menggunakan twirling untuk kamu dengan menggunakan pilihan. Dengan Executor, kamu menyatakan niat itu secara eksplisit dengan menggunakan box beranotasi dan samplex (dari Samplomatic).
Sampler (twirling dengan menggunakan pilihan):
sampler = Sampler(mode=backend)
sampler.options.twirling.enable_gates = True
sampler.options.twirling.enable_measure = True
Executor (twirling dengan menggunakan box dan samplex):
from samplomatic import build
from samplomatic.transpiler import generate_boxing_pass_manager
# 1. Group gates and measurements into annotated boxes with twirling annotations
boxes_pm = generate_boxing_pass_manager(
enable_gates=True, # gate twirling
enable_measures=True, # measurement twirling
)
boxed_circuit = boxes_pm.run(isa_circuit)
# 2. Build the (template circuit, samplex) pair.
# The template circuit's single-qubit gates are replaced by parameterized gates;
# the samplex encodes how to generate the randomized parameters at runtime.
template_circuit, samplex = build(boxed_circuit)
# 3. Append as a samplex item, specifying the number of randomizations
program = QuantumProgram(shots=1024)
program.append_samplex_item(
template_circuit,
samplex=samplex,
samplex_arguments={
"parameter_values": np.random.rand(10, 2), # original circuit params
},
shape=(28, 10), # 28 randomizations x 10 parameter sets
)
Kerana circuit templat dan samplex dibina di sisi klien, kamu boleh memeriksa dan mensampelnya secara tempatan untuk mengesahkan output sebelum menghantar apa-apa ke perkakasan.
Pengesahan: Sampel circuit templat secara tempatan
Kamu boleh menarik rawakan dari samplex dan mengikatnya kepada circuit
templat untuk mengesahkan bahawa samplex menghasilkan nilai parameter yang kamu jangkakan.
Nilai parameter yang dikembalikan oleh samplex.sample adalah serasi secara langsung dengan
parameter circuit templat.
# Check which inputs the samplex requires (for the twirling example above,
# this is just the original circuit's parameter values).
print(samplex.inputs())
# Bind the required inputs, then draw a few randomizations locally.
inputs = samplex.inputs().bind(
parameter_values=np.random.rand(2), # one set of the original circuit's params
)
outputs = samplex.sample(inputs, num_randomizations=3)
# Assign one randomization's parameter values to the template circuit and inspect it.
bound_template = template_circuit.assign_parameters(outputs["parameter_values"][0])
bound_template.draw("mpl", idle_wires=False)
Untuk melangkah lebih jauh, kamu boleh mengesahkan bahawa setiap rawakan adalah setara secara logik dengan
circuit asal dengan, contohnya, menukar kedua-duanya kepada objek Operator dan membandingkan pelaksanaan uniter mereka (selepas
mengambil kira pembetulan outputs["measurement_flips.<register>"] yang membatalkan
twirling pengukuran), atau dengan membandingkan nilai jangkaan dari larian
StatevectorSampler atau StatevectorEstimator tempatan. Lihat panduan Samplomatic
Input dan output Samplex
untuk panduan lengkap.
Langkah 4. Ubah cara shot diminta
Pindahkan shot dari PUB kepada QuantumProgram(shots=...). Dalam Executor, shots terpakai kepada keseluruhan kerja. Serahkan berbilang kerja jika kamu memerlukan bilangan shot yang berbeza.
Sampler:
# Run — shots are passed to run()
sampler = Sampler(mode=backend)
job = sampler.run([(isa_circuit, None, 25)])
Executor:
# Build a QuantumProgram — shots are on the program
program = QuantumProgram(shots=25)
program.append_circuit_item(isa_circuit)
Langkah 5. Kemaskini pilihan seperti yang diperlukan
Terdapat lebih sedikit pilihan tersedia untuk Executor berbanding Sampler, kerana pilihan mitigasi ralat kini berada dalam anotasi dan samplex kamu bukannya pilihan.
Terdapat juga perbezaan struktur dalam di mana tetapan berada.
-
Dengan Sampler, semuanya, termasuk pilihan yang menjejaskan pemprosesan pasca hasil, dikonfigurasi pada pilihan primitif atau dalam PUB.
-
Dengan Executor, pilihan yang menjejaskan cara hasil kerja dibentuk dan diproses pasca ditetapkan pada
QuantumProgram, bukan padaExecutorOptions.
Examples:
| Sampler | Executor |
|---|---|
shots | QuantumProgram(shots=...) |
meas_type | QuantumProgram(meas_level=...) |
ExecutorOptions hanya mengandungi tetapan pelaksanaan dan persekitaran peringkat rendah yang tidak mengubah struktur data yang dikembalikan. Ia mempunyai tiga kumpulan peringkat atas:
-
environment(EnvironmentOptions) -
execution(ExecutionOptions): Mengandungi lebih sedikit pilihan berbanding Sampler. Sebagai contoh, tiada pilihanmeas_typeExecutor.
Yang penting, pilihan twirling dan dynamical_decoupling wujud dalam Sampler tetapi tidak dalam Executor. Sebaliknya, nilai pilihan tersebut dinyatakan melalui model pelaksanaan berarah.
Example:
from qiskit_ibm_runtime import Executor, ExecutorOptions
options = ExecutorOptions(
environment={"log_level": "INFO"},
execution={"init_qubits": True},
)
# or mutate after construction:
options = ExecutorOptions()
options.environment.log_level = "INFO"
options.execution.init_qubits = True
executor = Executor(mode=backend, options=options)
Langkah 6. Kemas kini arahan run
Input kepada kerja Executor ialah program, bukannya PUB.
Sampler:
# Submit a job
sampler.run([(isa_circuit, parameter_values)])
Executor:
# Submit a job
executor.run(program)
Langkah 7. Ubah cara anda mengakses keputusan
Dalam Executor, keputusan adalah array NumPy, bukan objek BitArray. Gunakan rentetan nama sebagai indeks (result[0]["meas"]) dan anda akan mendapat semula np.ndarray. Tiada keperluan untuk mengingati laluan atribut .data.<register>.
Untuk mengemas kini daripada Sampler kepada Executor, tukar result[i].data.<reg> (BitArray) kepada result[i]["<reg>"] (np.ndarray), kemudian tulis semula pemprosesan pasca berasaskan get_counts sebagai operasi NumPy.
| Tugas | Sampler | Executor |
|---|---|---|
| Dapatkan data daftar | result[0].data.meas | result[0]["meas"] |
| Jenis data | BitArray | np.ndarray |
| Kamus kiraan | result[0].data.meas.get_counts() | Proses pasca array secara manual |
| Berbilang daftar | result[0].data.<name> bagi setiap daftar | result[0]["<name>"] bagi setiap daftar |
| Bentuk array CircuitItem | - | (parameter_sets, shots, register_bits) |
| Bentuk array SamplexItem | - | (randomizations, parameter_sets, shots, register_bits) |
| Buat asal twirling pengukuran | Automatik | result[i]["measurement_flips.<name>"] + XOR |
BitArray bagi Sampler menawarkan pembantu (get_counts, slice_bits, slice_shots, expectation_values, dan topeng pemilihan pasca). Executor mengembalikan tatasusunan NumPy mentah supaya anda boleh melakukan pemprosesan pasca ini dengan operasi NumPy standard.
Langkah 8. Kendalikan keputusan twirled (pembetulan bit-flip)
Apabila anda menggunakan twirling pengukuran melalui SamplexItem, Executor mengembalikan pengukuran mentah
(twirled) berserta pembetulan bit-flip yang diperlukan untuk membatalkan twirling.
Anda perlu menerapkannya secara manual; tiada apa yang dibetulkan secara tersirat.
Apabila menggunakan Executor, batalkan twirling secara eksplisit dengan menggunakan pembetulan measurement_flips.<reg> dan XOR, seperti yang ditunjukkan dalam contoh berikut:
# SamplexItem result shape: (randomizations, parameter_sets, shots, register_bits)
result_1 = result[1]["meas"] # example: (28, 10, 1024, 2)
# Bit-flip corrections to undo measurement twirling
flips_1 = result[1]["measurement_flips.meas"] # example: (28, 10, 1, 2)
# Undo the twirling through classical XOR (broadcasts over the shots axis)
unflipped_result_1 = result_1 ^ flips_1
Tiada langkah setara dalam Sampler kerana ia membatalkan twirling untuk anda secara automatik.
Contoh penuh: Migrasikan kerja pensampelan asas
Sampler
import numpy as np
from qiskit.circuit import QuantumCircuit
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
# 1. Account + backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
# 2. Circuit
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.h(1)
circuit.cz(0, 1)
circuit.h(1)
circuit.measure_all()
# 3. Transpile to ISA
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_circuit = pm.run(circuit)
# 4. Run — shots are passed to run()
sampler = Sampler(mode=backend)
job = sampler.run([(isa_circuit,)], shots=25)
result = job.result()
# 5. Access results: a BitArray keyed by register name
counts = result[0].data.meas.get_counts()
Executor
import numpy as np
from qiskit.circuit import QuantumCircuit
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, Executor
from qiskit_ibm_runtime.quantum_program import QuantumProgram
# 1. Account + backend (unchanged)
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
# 2. Circuit (unchanged)
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.h(1)
circuit.cz(0, 1)
circuit.h(1)
circuit.measure_all()
# 3. Transpile to ISA (unchanged)
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_circuit = pm.run(circuit)
# 4. Build a QuantumProgram — shots are on the program
program = QuantumProgram(shots=25)
program.append_circuit_item(isa_circuit)
# 5. Run
executor = Executor(mode=backend)
job = executor.run(program)
result = job.result()
# 6. Access results: a plain np.ndarray keyed by register name
# shape = (shots, register_bits)
meas = result[0]["meas"]