Langkau ke kandungan utama

Berpindah daripada Sampler kepada Executor

Panduan ini menerangkan cara memindahkan beban kerja pensampelan kuantum dari primitif IBM Quantum® Sampler kepada primitif Executor.

Beta release

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 AerSampler dalam qiskit-aer untuk 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 dalam qiskit-ibm-runtime v0.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).

Pemetaan konsep

Jadual berikut menunjukkan bagaimana konsep Sampler dipetakan kepada Executor.

KonsepSamplerExecutor
Importfrom qiskit_ibm_runtime import SamplerV2from qiskit_ibm_runtime import Executor
InputSenarai PUB (tuple)QuantumProgram daripada objek QuantumProgramItem
Circuit dan parameterTuple (circuit, params, shots)program.append_circuit_item(circuit, circuit_arguments=...)
TwirlingTwirlingOptionsSecara eksplisit melalui kotak beranotasi dan samplex (append_samplex_item)
Panggilan runsampler.run([pub, ...])executor.run(program)
Jenis hasilPrimitiveResult daripada SamplerPubResultQuantumProgramResult (boleh diulang)
Akses dataresult[0].data.<register> (BitArray)result[0]["<register>"] (np.ndarray)
Urus hingarPilihan terbina dalamPerlu digubah secara manual (anotasi, samplex, NoiseLearnerV3)

Gambaran keseluruhan langkah-langkah migrasi

  1. Pasang Samplomatic.

  2. Ubah import.

  3. Gantikan tuple PUB.

  4. Ubah cara shot dinyatakan.

  5. Kemaskini pilihan lain seperti yang diperlukan.

  6. Kemaskini arahan run.

  7. Kemaskini penghuraian hasil.

  8. Batalkan twirling.

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]
Version notes
  • qiskit-ibm-runtime v0.48.0 disyorkan kerana ia menambah pilihan meas_level = "both" dan kumpulan twirling local_c1.
  • qiskit >= 2.3.0 diperlukan.
  • samplomatic >= 0.18.0 diperlukan.

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: Melampirkan CircuitItem, 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: Melampirkan samplexItem, 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 pada ExecutorOptions.

Examples:

SamplerExecutor
shotsQuantumProgram(shots=...)
meas_typeQuantumProgram(meas_level=...)

ExecutorOptions hanya mengandungi tetapan pelaksanaan dan persekitaran peringkat rendah yang tidak mengubah struktur data yang dikembalikan. Ia mempunyai tiga kumpulan peringkat atas:

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.

TugasSamplerExecutor
Dapatkan data daftarresult[0].data.measresult[0]["meas"]
Jenis dataBitArraynp.ndarray
Kamus kiraanresult[0].data.meas.get_counts()Proses pasca array secara manual
Berbilang daftarresult[0].data.<name> bagi setiap daftarresult[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 pengukuranAutomatikresult[i]["measurement_flips.<name>"] + XOR
nota

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"]

Langkah seterusnya