Langkau ke kandungan utama

Migrasi ke primitif Qiskit Runtime V2

amaran

Primitif asal (dirujuk sebagai primitif V1), V1 Sampler dan V1 Estimator, telah ditamatkan dalam qiskit-ibm-runtime 0.23. Sokongan untuk primitif tersebut telah dihentikan pada 15 Ogos 2024.

Memandangkan primitif V1 telah ditamatkan, semua kod perlu dimigrasi untuk menggunakan antara muka V2. Panduan ini menerangkan apa yang berubah dalam primitif Qiskit Runtime V2 (tersedia dengan qiskit-ibm-runtime 0.21.0) dan sebabnya, menerangkan setiap primitif baru secara terperinci, dan memberikan contoh untuk membantu anda migrasi kod daripada primitif lama ke primitif V2. Contoh-contoh dalam panduan ini semuanya menggunakan primitif Qiskit Runtime, tetapi secara umumnya, perubahan yang sama juga terpakai pada implementasi primitif lain. Fungsi-fungsi yang unik untuk Qiskit Runtime seperti pengurangan ralat kekal unik untuk Qiskit Runtime.

Untuk maklumat tentang perubahan pada primitif rujukan Qiskit (kini dipanggil primitif statevector), lihat bahagian qiskit.primitives dalam halaman perubahan ciri Qiskit 1.0. Lihat StatevectorSampler dan StatevectorEstimator untuk implementasi rujukan primitif V2.

Gambaran keseluruhan​

Versi 2 bagi primitif diperkenalkan dengan kelas asas baru untuk kedua-dua Sampler dan Estimator (BaseSamplerV2 dan BaseEstimatorV2), bersama dengan jenis baharu untuk input dan output mereka.

Antara muka baharu ini membolehkan anda menentukan satu Circuit dan berbilang observable (jika menggunakan Estimator) serta set nilai parameter untuk Circuit tersebut, supaya sapuan ke atas set nilai parameter dan observable boleh ditentukan dengan cekap. Sebelum ini, anda perlu menentukan Circuit yang sama beberapa kali untuk memadankan saiz data yang hendak digabungkan. Selain itu, walaupun anda masih boleh menggunakan resilience_level (jika menggunakan Estimator) sebagai kawalan mudah, primitif V2 memberikan anda fleksibiliti untuk menghidupkan atau mematikan kaedah pengurangan / penindasan ralat secara individu bagi memenuhi keperluan anda.

Untuk mengurangkan jumlah masa pelaksanaan kerja, primitif V2 hanya menerima Circuit dan observable yang menggunakan arahan yang disokong oleh QPU (unit pemprosesan kuantum) sasaran. Circuit dan observable sedemikian dirujuk sebagai Circuit dan observable set seni bina arahan (ISA). Primitif V2 tidak melakukan operasi reka letak, penghalaan, dan penterjemahan. Lihat dokumentasi transpilasi untuk arahan mengubah Circuit.

Sampler V2 dipermudahkan untuk menumpukan pada tugas terasnya iaitu pensampelan daftar output daripada pelaksanaan Circuit kuantum. Ia mengembalikan sampel, yang jenisnya ditentukan oleh program, tanpa pemberat. Data output juga diasingkan mengikut nama daftar output yang ditentukan oleh program. Perubahan ini membolehkan sokongan masa hadapan untuk Circuit dengan aliran kawalan klasik.

Lihat rujukan API EstimatorV2 dan rujukan API SamplerV2 untuk butiran penuh.

Perubahan utama​

Import​

Untuk keserasian ke belakang, anda perlu mengimport primitif V2 secara eksplisit. Menentukan import <primitive>V2 as <primitive> tidak diwajibkan, tetapi memudahkan peralihan kod ke V2.

amaran

Selepas primitif V1 tidak lagi disokong, import <primitive> akan mengimport versi V2 bagi primitif yang ditentukan.

from qiskit_ibm_runtime import EstimatorV2 as Estimator
from qiskit_ibm_runtime import SamplerV2 as Sampler

Input dan output​

Input​

Kedua-dua SamplerV2 dan EstimatorV2 menerima satu atau lebih primitive unified blocs (PUB) sebagai input. Setiap PUB ialah tuple yang mengandungi satu Circuit dan data yang disiarkan ke Circuit tersebut, yang boleh merangkumi berbilang observable dan parameter. Setiap PUB mengembalikan satu keputusan.

  • Format PUB Sampler V2: (<circuit>, <parameter values>, <shots>), di mana <parameter values> dan <shots> adalah pilihan.
  • Format PUB Estimator V2: (<circuit>, <observables>, <parameter values>, <precision>), di mana <parameter values> dan <precision> adalah pilihan. Peraturan penyiaran Numpy digunakan ketika menggabungkan observable dan nilai parameter.

Selain itu, perubahan berikut telah dibuat:

  • Estimator V2 mempunyai hujah precision dalam kaedah run() yang menentukan ketepatan sasaran bagi anggaran nilai jangkaan.
  • Sampler V2 mempunyai hujah shots dalam kaedah run()-nya.
Contoh​

Contoh Estimator V2 yang menggunakan precision dalam run():

# Estimate expectation values for two PUBs, both with 0.05 precision.
estimator.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05)

Contoh Sampler V2 yang menggunakan shots dalam run():

# Sample two circuits at 128 shots each.
sampler.run([circuit1, circuit2], shots=128)

# Sample two circuits at different amounts of shots.
# The "None"s are necessary as placeholders
# for the lack of parameter values in this example.
sampler.run([
(circuit1, None, 123),
(circuit2, None, 456),
])

Output​

Output kini dalam format PubResult. PubResult ialah data dan metadata yang terhasil daripada pelaksanaan satu PUB.

  • Estimator V2 terus mengembalikan nilai jangkaan.

  • Bahagian data dalam PubResult Estimator V2 mengandungi kedua-dua nilai jangkaan dan ralat piawai (stds). V1 mengembalikan varians dalam metadata.

  • Sampler V2 mengembalikan pengukuran per-shot dalam bentuk bitstring, berbanding dengan taburan kuasi-kebarangkalian daripada antara muka V1. Bitstring menunjukkan hasil pengukuran, mengekalkan susunan shot mengikut urutan pengukuran.

  • Sampler V2 mempunyai kaedah kemudahan seperti get_counts() untuk membantu penghijrahan.

  • Objek keputusan Sampler V2 mengorganisasi data mengikut nama daftar klasik Circuit input, untuk keserasian dengan Circuit dinamik. Secara lalai, nama daftar klasik ialah meas, seperti yang ditunjukkan dalam contoh berikut. Semasa menentukan Circuit anda, jika anda membuat satu atau lebih daftar klasik dengan nama bukan lalai, gunakan nama tersebut untuk mendapatkan keputusan. Anda boleh mencari nama daftar klasik dengan menjalankan <circuit_name>.cregs. Contohnya, qc.cregs.

    # Define a quantum circuit with 2 qubits
    circuit = QuantumCircuit(2)
    circuit.h(0)
    circuit.cx(0, 1)
    circuit.measure_all()
    circuit.draw()
            β”Œβ”€β”€β”€β”      β–‘ β”Œβ”€β”
    q_0: ─ H β”œβ”€β”€β– β”€β”€β”€β–‘β”€β”€Mβ”œβ”€β”€β”€
    β””β”€β”€β”€β”˜β”Œβ”€β”΄β”€β” β–‘ β””β•₯β”˜β”Œβ”€β”
    q_1: ────── X β”œβ”€β–‘β”€β”€β•«β”€β”€Mβ”œ
    β””β”€β”€β”€β”˜ β–‘ β•‘ β””β•₯β”˜
    meas: 2/══════════════╩══╩═
    0 1

Contoh Estimator (input dan output)​

# Estimator V1: Execute 1 circuit with 4 observables
job = estimator_v1.run([circuit] * 4, [obs1, obs2, obs3, obs4])
evs = job.result().values

# Estimator V2: Execute 1 circuit with 4 observables
job = estimator_v2.run([(circuit, [obs1, obs2, obs3, obs4])])
evs = job.result()[0].data.evs

Contoh Sampler (input dan output)​

  # Sampler V1: Execute 1 circuit with 3 parameter sets
job = sampler_v1.run([circuit] * 3, [vals1, vals2, vals3])
dists = job.result().quasi_dists

# Sampler V2: Executing 1 circuit with 3 parameter sets
job = sampler_v2.run([(circuit, [vals1, vals2, vals3])])
counts = job.result()[0].data.meas.get_counts()

Contoh yang menggunakan daftar output berbeza

from qiskit import ClassicalRegister, QuantumRegister, QuantumCircuit
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler

alpha = ClassicalRegister(5, "alpha")
beta = ClassicalRegister(7, "beta")
qreg = QuantumRegister(12)

circuit = QuantumCircuit(qreg, alpha, beta)
circuit.h(0)
circuit.measure(qreg[:5], alpha)
circuit.measure(qreg[5:], beta)

service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=12)
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)

sampler = Sampler(backend)
job = sampler.run([isa_circuit])
result = job.result()
# Get results for the first (and only) PUB
pub_result = result[0]
print(f" >> Counts for the alpha output register: {pub_result.data.alpha.get_counts()}")
print(f" >> Counts for the beta output register: {pub_result.data.beta.get_counts()}")

Pilihan​

Pilihan ditentukan secara berbeza dalam primitif V2 seperti berikut:

  • SamplerV2 dan EstimatorV2 kini mempunyai kelas pilihan yang berasingan. Anda boleh melihat pilihan yang tersedia dan mengemas kini nilai pilihan semasa atau selepas permulaan primitif.
  • Berbanding kaedah set_options(), pilihan primitif V2 menggunakan kaedah update() yang menerapkan perubahan pada atribut options.
  • Jika anda tidak menentukan nilai untuk sesuatu pilihan, ia diberi nilai khas Unset dan lalai pelayan digunakan.
  • Untuk primitif V2, atribut options adalah jenis Python dataclass. Anda boleh menggunakan kaedah bawaan asdict untuk menukarnya kepada kamus.

Lihat rujukan API untuk senarai pilihan yang tersedia.

from dataclasses import asdict
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import EstimatorV2 as Estimator

service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)

# Setting options during primitive initialization
estimator = Estimator(backend, options={"resilience_level": 2})

# Setting options after primitive initialization
# This uses auto complete.
estimator.options.default_shots = 4000
# This does bulk update.
estimator.options.update(default_shots=4000, resilience_level=2)

# Print the dictionary format.
# Server defaults are used for unset options.
print(asdict(estimator.options))
from dataclasses import asdict
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import SamplerV2 as Sampler

service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)

# Setting options during primitive initialization
sampler = Sampler(backend, options={"default_shots": 4096})

# Setting options after primitive initialization
# This uses auto complete.
sampler.options.dynamical_decoupling.enable = True
# Turn on gate twirling. Requires qiskit_ibm_runtime 0.23.0 or later.
sampler.options.twirling.enable_gates = True

# This does bulk update. The value for default_shots is overridden if you specify shots with run() or in the PUB.
sampler.options.update(default_shots=1024, dynamical_decoupling={"sequence_type": "XpXm"})

# Print the dictionary format.
# Server defaults are used for unset options.
print(asdict(sampler.options))

Pengurangan dan penindasan ralat​

  • Memandangkan Sampler V2 mengembalikan sampel tanpa pasca-pemprosesan, ia tidak menyokong tahap ketahanan (resilience levels).

  • Sampler V2 tidak menyokong optimization_level.

  • Estimator V2 akan menggugurkan sokongan untuk optimization_level pada atau sekitar 30 September 2024.

  • Estimator V2 tidak menyokong tahap ketahanan 3. Ini kerana tahap ketahanan 3 dalam V1 Estimator menggunakan Probabilistic Error Cancellation (PEC), yang terbukti memberikan keputusan tidak berat sebelah dengan kos masa pemprosesan eksponen. Tahap 3 dibuang untuk menarik perhatian kepada pertukaran tersebut. Walau bagaimanapun, anda masih boleh menggunakan PEC sebagai kaedah pengurangan ralat dengan menentukan pilihan pec_mitigation.

  • Estimator V2 menyokong resilience_level 0-2, seperti yang diterangkan dalam jadual berikut. Pilihan-pilihan ini lebih canggih berbanding rakan sejawat V1. Anda juga boleh menghidupkan / mematikan kaedah pengurangan / penindasan ralat individu secara eksplisit.

    Tahap 1Tahap 2
    Measurement twirlingMeasurement twirling
    Readout error mitigationReadout error mitigation
    ZNE
from dataclasses import asdict
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import EstimatorV2 as Estimator

service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)

# Setting options during primitive initialization
estimator = Estimator(backend)

# Set resilience_level to 0
estimator.options.resilience_level = 0

# Turn on measurement error mitigation
estimator.options.resilience.measure_mitigation = True
from qiskit_ibm_runtime import SamplerV2 as Sampler

sampler = Sampler(backend)
# Turn on dynamical decoupling with sequence XpXm.
sampler.options.dynamical_decoupling.enable = True
sampler.options.dynamical_decoupling.sequence_type = "XpXm"

print(f">> dynamical decoupling sequence to use: {sampler.options.dynamical_decoupling.sequence_type}")

Transpilasi​

Primitif V2 hanya menyokong Circuit yang mematuhi Set Seni Bina Arahan (ISA) bagi Backend tertentu. Memandangkan primitif tidak melakukan operasi reka letak, penghalaan, dan penterjemahan, pilihan transpilasi yang berkaitan daripada V1 tidak disokong.

Status kerja​

Primitif V2 mempunyai kelas RuntimeJobV2 baharu, yang diwarisi daripada BasePrimitiveJob. Kaedah status() bagi kelas baharu ini mengembalikan string berbanding enum JobStatus daripada Qiskit. Lihat rujukan API RuntimeJobV2 untuk butiran.

job = estimator.run(...)

# check if a job is still running
print(f"Job {job.job_id()} is still running: {job.status() == "RUNNING"}")

Langkah-langkah migrasi ke Estimator V2​

  1. Gantikan from qiskit_ibm_runtime import Estimator dengan from qiskit_ibm_runtime import EstimatorV2 as Estimator.

  2. Buang sebarang pernyataan from qiskit_ibm_runtime import Options, kerana kelas Options tidak digunakan oleh primitif V2. Sebaliknya, anda boleh menghantar pilihan sebagai kamus semasa memulakan kelas EstimatorV2 (contohnya estimator = Estimator(backend, options={"dynamical_decoupling": {"enable": True}})), atau tetapkannya selepas permulaan:

    estimator = Estimator(backend)
    estimator.options.dynamical_decoupling.enable = True
  3. Semak semua pilihan yang disokong dan buat kemas kini mengikutnya.

  4. Kumpulkan setiap Circuit yang ingin anda jalankan bersama observable dan nilai parameter yang ingin anda terapkan pada Circuit tersebut dalam satu tuple (PUB). Contohnya, gunakan (circuit1, observable1, parameter_set1) jika anda ingin menjalankan circuit1 dengan observable1 dan parameter_set1.

  5. Anda mungkin perlu membentuk semula tatasusunan observable atau set parameter jika anda ingin menerapkan hasil darab luar mereka. Contohnya, tatasusunan observable bersaiz (4, 1) dan tatasusunan set parameter bersaiz (1, 6) akan memberikan keputusan (4, 6) nilai jangkaan. Lihat peraturan penyiaran Numpy untuk butiran lanjut.

  6. Anda boleh secara pilihan menentukan ketepatan yang anda inginkan untuk PUB khusus tersebut.

  7. Kemas kini kaedah run() estimator untuk menghantar senarai PUB. Contohnya, run([(circuit1, observable1, parameter_set1)]). Anda boleh secara pilihan menentukan precision di sini, yang akan terpakai pada semua PUB.

  8. Keputusan kerja Estimator V2 dikumpulkan mengikut PUB. Anda boleh melihat nilai jangkaan dan ralat piawai untuk setiap PUB dengan mengindeksnya. Contohnya:

pub_result = job.result()[0]
print(f">>> Expectation values: {pub_result.data.evs}")
print(f">>> Standard errors: {pub_result.data.stds}")

Contoh lengkap Estimator​

Jalankan satu eksperimen​

Gunakan Estimator untuk menentukan nilai jangkaan bagi sepasang Circuit-observable tunggal.

import numpy as np
from qiskit.circuit.library import IQP
from qiskit.quantum_info import SparsePauliOp, random_hermitian
from qiskit_ibm_runtime import EstimatorV2 as Estimator, QiskitRuntimeService

service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
estimator = Estimator(backend)

n_qubits = 127

mat = np.real(random_hermitian(n_qubits, seed=1234))
circuit = IQP(mat)
observable = SparsePauliOp("Z" * n_qubits)

pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_circuit = pm.run(circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)

job = estimator.run([(isa_circuit, isa_observable)])
result = job.result()

print(f" > Expectation value: {result[0].data.evs}")
print(f" > Metadata: {result[0].metadata}")

Jalankan beberapa eksperimen dalam satu kerja​

Gunakan Estimator untuk menentukan nilai jangkaan bagi beberapa pasangan Circuit-observable.

service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)

n_qubits = 3
rng = np.random.default_rng()
mats = [np.real(random_hermitian(n_qubits, seed=rng)) for _ in range(3)]
circuits = [IQP(mat) for mat in mats]
observables = [
SparsePauliOp("X" * n_qubits),
SparsePauliOp("Y" * n_qubits),
SparsePauliOp("Z" * n_qubits),
]

isa_circuits = pm.run(circuits)
isa_observables = [ob.apply_layout(isa_circuits[0].layout) for ob in observables]

estimator = Estimator(backend)
job = estimator.run([(isa_circuits[0], isa_observables[0]),(isa_circuits[1], isa_observables[1]),(isa_circuits[2], isa_observables[2])])
job_result = job.result()
for idx in range(len(job_result)):
pub_result = job_result[idx]
print(f">>> Expectation values for PUB {idx}: {pub_result.data.evs}")
print(f">>> Standard errors for PUB {idx}: {pub_result.data.stds}")

Jalankan Circuit berparameter​

Gunakan Estimator untuk menjalankan beberapa eksperimen dalam satu kerja, dengan memanfaatkan nilai parameter bagi meningkatkan kebolehgunaan semula Circuit. Dalam contoh berikut, perhatikan bahawa langkah 1 dan 2 adalah sama untuk V1 dan V2.

import numpy as np

from qiskit.circuit import QuantumCircuit, Parameter
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService

# Step 1: Map classical inputs to a quantum problem

theta = Parameter("ΞΈ")

chsh_circuit = QuantumCircuit(2)
chsh_circuit.h(0)
chsh_circuit.cx(0, 1)
chsh_circuit.ry(theta, 0)

number_of_phases = 21
phases = np.linspace(0, 2 * np.pi, number_of_phases)
individual_phases = [[ph] for ph in phases]

ZZ = SparsePauliOp.from_list([("ZZ", 1)])
ZX = SparsePauliOp.from_list([("ZX", 1)])
XZ = SparsePauliOp.from_list([("XZ", 1)])
XX = SparsePauliOp.from_list([("XX", 1)])
ops = [ZZ, ZX, XZ, XX]

# Step 2: Optimize problem for quantum execution.

service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
chsh_isa_circuit = pm.run(chsh_circuit)
isa_observables = [operator.apply_layout(chsh_isa_circuit.layout) for operator in ops]

from qiskit_ibm_runtime import EstimatorV2 as Estimator

# Step 3: Execute using Qiskit primitives.

# Reshape observable array for broadcasting
reshaped_ops = np.fromiter(isa_observables, dtype=object)
reshaped_ops = reshaped_ops.reshape((4, 1))

estimator = Estimator(backend, options={"default_shots": int(1e4)})
job = estimator.run([(chsh_isa_circuit, reshaped_ops, individual_phases)])
# Get results for the first (and only) PUB
pub_result = job.result()[0]
print(f">>> Expectation values: {pub_result.data.evs}")
print(f">>> Standard errors: {pub_result.data.stds}")
print(f">>> Metadata: {pub_result.metadata}")

Gunakan Session dan pilihan lanjutan​

Terokai Session dan pilihan lanjutan untuk mengoptimumkan prestasi Circuit pada QPU.

awas

Blok kod berikut akan mengembalikan ralat bagi pengguna pada Pelan Terbuka kerana ia menggunakan Session. Beban kerja pada Pelan Terbuka hanya boleh dijalankan dalam mod kerja atau mod kelompok.

import numpy as np
from qiskit.circuit.library import IQP
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.quantum_info import SparsePauliOp, random_hermitian
from qiskit_ibm_runtime import QiskitRuntimeService, Session, EstimatorV2 as Estimator

n_qubits = 127

rng = np.random.default_rng(1234)
mat = np.real(random_hermitian(n_qubits, seed=rng))
circuit = IQP(mat)
mat = np.real(random_hermitian(n_qubits, seed=rng))
another_circuit = IQP(mat)
observable = SparsePauliOp("X" * n_qubits)
another_observable = SparsePauliOp("Y" * n_qubits)

pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_circuit = pm.run(circuit)
another_isa_circuit = pm.run(another_circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)
another_isa_observable = another_observable.apply_layout(another_isa_circuit.layout)

service = QiskitRuntimeService()

backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)

with Session(backend=backend) as session:
estimator = Estimator()

estimator.options.resilience_level = 1

job = estimator.run([(isa_circuit, isa_observable)])
another_job = estimator.run([(another_isa_circuit, another_isa_observable)])
result = job.result()
another_result = another_job.result()

# first job
print(f" > Expectation value: {result[0].data.evs}")
print(f" > Metadata: {result[0].metadata}")

# second job
print(f" > Another Expectation value: {another_result[0].data.evs}")
print(f" > More Metadata: {another_result[0].metadata}")

Langkah-langkah untuk berpindah ke Sampler V2​

  1. Gantikan from qiskit_ibm_runtime import Sampler dengan from qiskit_ibm_runtime import SamplerV2 as Sampler.
  2. Buang sebarang pernyataan from qiskit_ibm_runtime import Options, kerana kelas Options tidak digunakan oleh primitif V2. Sebaliknya, anda boleh menghantar pilihan sebagai kamus semasa memulakan kelas SamplerV2 (contohnya sampler = Sampler(backend, options={"default_shots": 1024})), atau tetapkannya selepas permulaan:
    sampler = Sampler(backend)
    sampler.options.default_shots = 1024
  3. Semak semua pilihan yang disokong dan buat kemas kini yang sesuai.
  4. Kumpulkan setiap Circuit yang ingin anda jalankan bersama observable dan nilai parameter yang ingin anda gunakan pada Circuit itu dalam satu tuple (PUB). Contohnya, gunakan (circuit1, parameter_set1) jika anda ingin menjalankan circuit1 dengan parameter_set1. Anda boleh menentukan bilangan shot yang dikehendaki untuk PUB tertentu itu secara pilihan.
  5. Kemas kini kaedah run() Sampler untuk menghantar senarai PUB. Contohnya, run([(circuit1, parameter_set1)]). Anda boleh menentukan shots secara pilihan di sini, yang akan digunakan pada semua PUB.
  6. Keputusan kerja Sampler V2 dikumpulkan mengikut PUB. Anda boleh melihat data output untuk setiap PUB dengan mengindeksnya. Walaupun Sampler V2 mengembalikan sampel tanpa pemberat, kelas keputusan mempunyai kaedah kemudahan untuk mendapatkan kiraan. Contohnya:
pub_result = job.result()[0]
print(f">>> Counts: {pub_result.data.meas.get_counts()}")
print(f">>> Per-shot measurement: {pub_result.data.meas.get_counts()}")
nota

Anda memerlukan nama daftar klasik untuk mendapatkan keputusan. Secara lalai, ia dinamakan meas apabila anda menggunakan measure_all(). Apabila menentukan Circuit anda, jika anda mencipta satu atau lebih daftar klasik dengan nama bukan lalai, gunakan nama tersebut untuk mendapatkan keputusan. Anda boleh mencari nama daftar klasik dengan menjalankan <circuit_name>.cregs. Contohnya, qc.cregs.

Contoh lengkap Sampler​

Jalankan satu eksperimen​

Gunakan Sampler untuk menentukan kiraan atau taburan kebarangkalian separuh bagi satu Circuit tunggal.

import numpy as np
from qiskit.circuit.library import IQP
from qiskit.quantum_info import random_hermitian
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

service = QiskitRuntimeService()

backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)

n_qubits = 127

mat = np.real(random_hermitian(n_qubits, seed=1234))
circuit = IQP(mat)
circuit.measure_all()

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)

sampler = Sampler(backend)
job = sampler.run([isa_circuit])
result = job.result()

Jalankan beberapa eksperimen dalam satu kerja​

Gunakan Sampler untuk menentukan kiraan atau taburan kebarangkalian separuh bagi beberapa Circuit dalam satu kerja.

import numpy as np
from qiskit.circuit.library import IQP
from qiskit.quantum_info import random_hermitian
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler

service = QiskitRuntimeService()

backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)

n_qubits = 127

rng = np.random.default_rng()
mats = [np.real(random_hermitian(n_qubits, seed=rng)) for _ in range(3)]
circuits = [IQP(mat) for mat in mats]
for circuit in circuits:
circuit.measure_all()

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuits = pm.run(circuits)

sampler = Sampler(backend)
job = sampler.run(isa_circuits)
result = job.result()

for idx, pub_result in enumerate(result):
print(f" > Counts for pub {idx}: {pub_result.data.meas.get_counts()}")

Jalankan Circuit berparameter​

Jalankan beberapa eksperimen dalam satu kerja, memanfaatkan nilai parameter untuk meningkatkan kebolehgunaan semula Circuit.

import numpy as np
from qiskit.circuit.library import RealAmplitudes
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService

# Step 1: Map classical inputs to a quantum problem
num_qubits = 127
circuit = RealAmplitudes(num_qubits=num_qubits, reps=2)
circuit.measure_all()

# Define three sets of parameters for the circuit
rng = np.random.default_rng(1234)
parameter_values = [
rng.uniform(-np.pi, np.pi, size=circuit.num_parameters) for _ in range(3)
]

# Step 2: Optimize problem for quantum execution.

service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=num_qubits)

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)

# Step 3: Execute using Qiskit primitives.

from qiskit_ibm_runtime import SamplerV2 as Sampler

sampler = Sampler(backend)
job = sampler.run([(isa_circuit, parameter_values)])
result = job.result()
# Get results for the first (and only) PUB
pub_result = result[0]
# Get counts from the classical register "meas".
print(f" >> Counts for the meas output register: {pub_result.data.meas.get_counts()}")

Gunakan Session dan pilihan lanjutan​

Terokai Session dan pilihan lanjutan untuk mengoptimumkan prestasi Circuit pada QPU.

awas

Blok kod berikut akan mengembalikan ralat bagi pengguna dalam Pelan Terbuka kerana ia menggunakan Session. Beban kerja dalam Pelan Terbuka hanya boleh dijalankan dalam mod kerja atau mod kelompok.

import numpy as np
from qiskit.circuit.library import IQP
from qiskit.quantum_info import random_hermitian
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler, Session

n_qubits = 127

rng = np.random.default_rng(1234)
mat = np.real(random_hermitian(n_qubits, seed=rng))
circuit = IQP(mat)
circuit.measure_all()
mat = np.real(random_hermitian(n_qubits, seed=rng))
another_circuit = IQP(mat)
another_circuit.measure_all()

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)
another_isa_circuit = pm.run(another_circuit)

service = QiskitRuntimeService()

# Turn on dynamical decoupling with sequence XpXm.
sampler.options.dynamical_decoupling.enable = True
sampler.options.dynamical_decoupling.sequence_type = "XpXm"

backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)

with Session(backend=backend) as session:
sampler = Sampler()
job = sampler.run([isa_circuit])
another_job = sampler.run([another_isa_circuit])
result = job.result()
another_result = another_job.result()

# first job
print(f" > Counts for job 1: {result[0].data.meas.get_counts()}")

# second job
print(f" > Counts for job 2: {another_result[0].data.meas.get_counts()}")

Langkah seterusnya​

Cadangan
Source: IBM Quantum docs β€” updated 27 Apr 2026
English version on doQumentation β€” updated 7 Mei 2026
This translation based on the English version of 11 Mac 2026