Penyiaran Executor
Data yang diberikan kepada primitif Executor boleh disusun dalam pelbagai bentuk untuk memberikan fleksibiliti dalam beban kerja melalui penyiaran. Panduan ini menerangkan cara Executor mengendalikan input dan output tatasusunan menggunakan semantik penyiaran. Memahami konsep-konsep ini akan membantu anda menyapu nilai parameter dengan cekap, menggabungkan pelbagai konfigurasi, dan mentafsir bentuk data yang dikembalikan.
Contoh-contoh dalam topik ini tidak boleh dijalankan secara tersendiri. Contoh-contoh ini mengandaikan anda telah menakrifkan Circuit yang sesuai, menggunakan pengurus laluan Samplomatic untuk menambah kotak dan anotasi, serta menggunakan kaedah build Samplomatic untuk mendapatkan Circuit templat dan samplex bagi setiap blok kod, mengikut keperluan.
Contoh permulaan pantas
Contoh ini menunjukkan idea teras. Ia mencipta Circuit berparameter dan lima konfigurasi parameter yang berbeza. Executor menjalankan semua lima konfigurasi dan mengembalikan data yang disusun mengikut konfigurasi, dengan satu keputusan bagi setiap daftar klasikal dalam setiap item program kuantum.
Selebihnya panduan ini merujuk kembali kepada contoh ini untuk menerangkan cara ia berfungsi dan cara membina sapuan yang lebih kompleks, termasuk rawakan berasaskan Samplomatic dan input.
import numpy as np
from qiskit.circuit import Parameter, QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService, Executor
from qiskit_ibm_runtime.quantum_program import QuantumProgram
from qiskit.transpiler import generate_preset_pass_manager
# A circuit with 2 parameters
# This circuit is used throughout the rest of this guide.
circuit = QuantumCircuit(4)
circuit.rx(Parameter("a"), 0)
circuit.rx(Parameter("b"), 1)
circuit.h(2)
circuit.cx(2, 3)
circuit.measure_all()
# 5 different parameter configurations (shape: 5 configurations × 2 parameters)
parameter_values = np.linspace(0, np.pi, 10).reshape(5, 2)
# Initialize the service and choose a backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
# Transpile to ISA circuit
preset_pass_manager = generate_preset_pass_manager(
backend=backend,
optimization_level=3,
)
isa_circuit = preset_pass_manager.run(circuit)
# This program is used throughout the rest of this guide.
program = QuantumProgram(shots=1024)
program.append_circuit_item(isa_circuit, circuit_arguments=parameter_values)
# initialize an Executor with default options
executor = Executor(mode=backend)
# Run and get results
result = executor.run(program).result()
# result is a list with one entry per program item
# result[0] is a dict mapping classical register names to data arrays
# Output bool arrays have shape (5, 1024, 4)
# 5 = number of parameter configurations
# 1024 = number of shots
# 4 = bits in the classical register
result[0]["meas"]
Paksi intrinsik dan ekstrinsik
Penyiaran hanya dikenakan kepada paksi ekstrinsik. Paksi intrinsik sentiasa dikekalkan seperti yang ditentukan.
-
Paksi intrinsik (paling kanan): Ditentukan oleh jenis data. Sebagai contoh, jika Circuit anda mempunyai tiga parameter, maka nilai parameter memerlukan tiga nombor, memberikan bentuk intrinsik
(3,). -
Paksi ekstrinsik (paling kiri): Dimensi sapuan anda. Ini menentukan bilangan konfigurasi yang ingin anda jalankan.
| Jenis input | Bentuk intrinsik | Contoh bentuk penuh |
|---|---|---|
| Nilai parameter (n parameter) | (n,) | (5, 3) untuk lima konfigurasi dan tiga parameter |
| Input skalar (contohnya, faktor skala hingar) | () | (4,) untuk empat konfigurasi |
| Observable (jika berkenaan) | berbeza-beza | Bergantung kepada jenis observable |
Contoh
Pertimbangkan Circuit dengan dua parameter yang ingin anda sapu melalui grid konfigurasi 4x3, dengan nilai parameter dan faktor skala hingar yang berbeza:
import numpy as np
# Parameter values: 4 configurations along axis 0, intrinsic shape (2,)
# Full shape: (4, 1, 2) - the "1" allows broadcasting with noise_scale
parameter_values = np.array([
[[0.1, 0.2]],
[[0.3, 0.4]],
[[0.5, 0.6]],
[[0.7, 0.8]],
]) # shape (4, 1, 2)
# Noise scale: 3 configurations, intrinsic shape () (scalar)
# Full shape: (3,)
noise_scale = np.array([0.8, 1.0, 1.2]) # shape (3,)
# Extrinsic shapes: (4, 1) and (3,) → broadcast to (4, 3)
# Result: 12 total configurations in a 4×3 grid
program.append_samplex_item(
template_circuit,
samplex=samplex,
samplex_arguments={
"parameter_values": parameter_values,
"noise_scales.mod_ref1": noise_scale,
},
)
Bentuk-bentuknya adalah seperti berikut:
| Input | Bentuk penuh | Bentuk ekstrinsik | Bentuk intrinsik |
|---|---|---|---|
parameter_values | (4, 1, 2) | (4, 1) | (2,) |
noise_scale | (3,) | (3,) | () |
| Disiarkan | Tiada | (4, 3) | Tiada |
Bentuk tatasusunan output
Tatasusunan output mengikuti corak ekstrinsik/intrinsik yang sama:
- Bentuk ekstrinsik: Sepadan dengan bentuk penyiaran semua input
- Bentuk intrinsik: Ditentukan oleh jenis output
Output yang paling biasa adalah data rentetan bit daripada ukuran, yang diformat sebagai tatasusunan nilai boolean:
| Jenis output | Bentuk intrinsik | Penerangan |
|---|---|---|
| Data daftar klasikal | (num_shots, creg_size) | Data rentetan bit daripada ukuran |
Contoh
Jika anda memberikan input dengan bentuk ekstrinsik (4, 1) dan (3,), bentuk ekstrinsik yang disiarkan adalah (4, 3). Kod berikut menggunakan Circuit dengan 1024 tembakan dan daftar klasikal 4-bit (seperti yang ditakrifkan dalam contoh Permulaan pantas):
# Input extrinsic shapes: (4, 1) and (3,) → (4, 3)
# Output for classical register "meas":
# extrinsic: (4, 3)
# intrinsic: (1024, 4) - shots × bits
# full shape: (4, 3, 1024, 4)
result = executor.run(program).result()
meas_data = result[0]["meas"] # result[0] for first program item
print(meas_data.shape) # (4, 3, 1024, 4)
# Access a specific configuration
config_2_1 = meas_data[2, 1, :, :] # shape (1024, 4)
Setiap konfigurasi menjalankan bilangan tembakan penuh yang ditentukan dalam program kuantum. Tembakan tidak dibahagikan antara konfigurasi. Sebagai contoh, jika anda meminta 1024 tembakan dan mempunyai 10 konfigurasi, setiap konfigurasi menjalankan 1024 tembakan (jumlah 10,240 tembakan dilaksanakan).
Rawakan dan parameter shape
Apabila menggunakan samplex, setiap elemen bentuk ekstrinsik sepadan dengan pelaksanaan Circuit yang bebas. Samplex biasanya menyuntik rawakan (contohnya, gate twirling) ke dalam setiap pelaksanaan, jadi walaupun tanpa meminta berbilang rawakan secara eksplisit, setiap elemen menerima realisasi rawak.
Kamu boleh menggunakan parameter shape untuk menambah bentuk ekstrinsik bagi item tersebut, dengan berkesan menambah paksi yang sepadan khusus untuk merawakkan konfigurasi yang sama berkali-kali. Ia mesti boleh disiarkan daripada bentuk yang tersirat dalam samplex_arguments anda. Paksi di mana shape melebihi bentuk tersirat menyenaraikan rawakan bebas tambahan.
Tiada paksi rawakan eksplisit
Jika anda tidak menyertakan shape (atau menetapkannya untuk sepadan dengan bentuk input anda), anda mendapat satu pelaksanaan bagi setiap konfigurasi input. Setiap pelaksanaan masih dirawakkan oleh samplex, tetapi dengan hanya satu realisasi rawak anda tidak mendapat manfaat daripada pengambilan purata berbilang rawakan.
Jika anda biasa menghidupkan twirling dengan bendera mudah seperti twirling=True, perlu diingat bahawa Executor memerlukan anda meminta berbilang rawakan secara eksplisit dengan argumen shape agar rutin pasca-pemprosesan anda mendapat manfaat daripada pengambilan purata berbilang rawakan. Satu rawakan (lalai apabila shape tidak disertakan) menerapkan gate rawak tetapi biasanya tidak menawarkan kelebihan berbanding menjalankan Circuit asas tanpa rawakan.
Contoh berikut menunjukkan tingkah laku lalai:
program.append_samplex_item(
template_circuit,
samplex=samplex,
samplex_arguments={
"parameter_values": np.random.rand(10, 2), # extrinsic (10,)
},
# shape defaults to (10,) - one randomized execution per config
)
# Output shape for "meas": (10, num_shots, creg_size)
Satu paksi rawakan
Untuk menjalankan berbilang rawakan bagi setiap konfigurasi, lanjutkan bentuk dengan paksi tambahan. Sebagai contoh, kod berikut menjalankan 20 rawakan untuk setiap 10 konfigurasi parameter:
program.append_samplex_item(
template_circuit,
samplex=samplex,
samplex_arguments={
"parameter_values": np.random.rand(10, 2), # extrinsic (10,)
},
shape=(20, 10), # 20 randomizations × 10 configurations
)
# Output shape for "meas": (20, 10, num_shots, creg_size)
Berbilang paksi rawakan
Kamu boleh menyusun rawakan ke dalam grid berbilang dimensi. Ini berguna untuk analisis berstruktur, contohnya, memisahkan rawakan mengikut jenis atau mengumpulkannya untuk pemprosesan statistik.
Di sini, bentuk ekstrinsik input (10,) disiarkan kepada bentuk yang diminta (2, 14, 10), dengan paksi 0 dan 1 diisi oleh rawakan bebas.
program.append_samplex_item(
template_circuit,
samplex=samplex,
samplex_arguments={
"parameter_values": np.random.rand(10, 2), # extrinsic (10,)
},
# 2×14=28 randomizations per configuration, 10 configurations
# Or you could set shape=(28, 10) for the same effect
shape=(2, 14, 10),
)
# Output shape for "meas": (2, 14, 10, num_shots, creg_size)
Cara shape dan bentuk input berinteraksi
Parameter shape mesti boleh disiarkan daripada bentuk ekstrinsik input anda. Ini bermakna:
- Bentuk input dengan dimensi bersaiz-1 boleh dikembangkan untuk sepadan dengan
shape. - Bentuk input mesti diselaraskan dari kanan dengan
shape. - Paksi dalam
shapeyang melebihi dimensi input menyenaraikan rawakan.
Perlu diingat bahawa shape boleh mengandungi dimensi bersaiz-1 yang dikembangkan untuk sepadan dengan dimensi input, seperti yang ditunjukkan dalam baris terakhir jadual berikut.
Contoh-contoh:
| Input ekstrinsik | Shape | Keputusan |
|---|---|---|
| (10,) | (10,) | 10 konfigurasi, 1 rawakan setiap satu |
| (10,) | (5, 10) | 10 konfigurasi, 5 rawakan setiap satu |
| (10,) | (2, 3, 10) | 10 konfigurasi, 2×3=6 rawakan setiap satu |
| (4, 1) | (4, 5) | 4 konfigurasi, 5 rawakan setiap satu |
| (4, 3) | (2, 4, 3) | 4×3=12 konfigurasi, 2 rawakan setiap satu |
| (4, 3) | (2, 1, 3) | 4×3=12 konfigurasi, 2 rawakan setiap satu (1 dikembangkan menjadi 4) |
Indeks ke dalam keputusan
Dengan paksi rawakan, anda boleh mengindeks ke dalam kombinasi rawakan/parameter tertentu:
# Using shape=(2, 14, 10) with input extrinsic shape (10,), and
# 1024 shots and 4 classical registers.
result = executor.run(program).result()
meas_data = result[0]["meas"] # shape (2, 14, 10, 1024, 4)
# Get all shots for randomization (0, 7) and parameter config 3
specific = meas_data[0, 7, 3, :, :] # shape (1024, 4)
# Average over all randomizations for parameter config 5 on bit 2
averaged = meas_data[:, :, 5, :, 2].mean(axis=(0, 1))
Corak biasa
Sapu satu parameter
Gunakan kod seperti berikut untuk menyapu satu parameter sambil mengekalkan yang lain tetap:
# Circuit has 2 parameters, sweep first one over 20 values
sweep_values = np.linspace(0, 2*np.pi, 20)
parameter_values = np.column_stack([
sweep_values,
np.full(20, 0.5),
]) # shape (20, 2)
Cipta sapuan grid 2D
Untuk mencipta grid merentasi tiga parameter:
# Sweep param 0 over 10 values, param 1 over 8 values, param 2 fixed
p0 = np.linspace(0, np.pi, 10)[:, np.newaxis, np.newaxis] # (10, 1, 1)
p1 = np.linspace(0, np.pi, 8)[np.newaxis, :, np.newaxis] # (1, 8, 1)
p2 = np.array([[[0.5]]]) # (1, 1, 1)
parameter_values = np.broadcast_arrays(p0, p1, p2)
parameter_values = np.stack(parameter_values, axis=-1).squeeze() # (10, 8, 3)
# Extrinsic shape: (10, 8), intrinsic shape: (3,)
Menggabungkan berbilang input
Apabila menggabungkan input dengan bentuk intrinsik yang berbeza, selaraskan dimensi ekstrinsik menggunakan paksi bersaiz-1:
# 4 parameter configurations, 3 noise scales → 4×3 = 12 total configurations
parameter_values = np.random.rand(4, 1, 2) # extrinsic (4, 1), intrinsic (2,)
noise_scale = np.array([0.8, 1.0, 1.2]) # extrinsic (3,), intrinsic ()
# Broadcasted extrinsic shape: (4, 3)
Langkah seterusnya
- Semak gambaran keseluruhan penyiaran.
- Fahami input dan output Executor.