Mga input at output ng Executor
Mga bersyon ng package
Ang code sa pahinang ito ay binuo gamit ang mga sumusunod na kinakailangan. Inirerekumenda naming gamitin ang mga bersyong ito o mas bago.
qiskit[all]~=2.4.0
qiskit-ibm-runtime~=0.46.1
samplomatic~=0.18.0
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-ibm-runtime samplomatic
Ang Executor primitive ay bahagi ng directed execution model, na nagbibigay ng mas maraming kakayahang umangkop kapag nag-cu-customize ng isang workflow ng error mitigation.
Ang mga input at output ng Executor primitive ay napaka-iba mula sa mga Sampler at Estimator primitive. Halimbawa, sa halip na tumanggap ng listahan ng mga PUB bilang input, ang Executor ay tumatanggap ng isang QuantumProgram, na naglalaman ng listahan ng mga object na QuantumProgramItem. Ang mga container class na ito ay nagbibigay sa iyo ng mas maraming kakayahang umangkop kaysa sa isang PUB, na isang simpleng tuple data structure.
Ang output ng Executor ay isang QuantumProgramResult, na isang iterable at naglalaman ng isang elemento para sa bawat input na QuantumProgramItem.
Mga input: Mga quantum program
Tulad ng nabanggit kanina, ang input sa isang Executor primitive ay isang QuantumProgram, na isang iterable ng mga object na QuantumProgramItem. Ang mga object na ito ay maaaring may dalawang uri:
CircuitItem, na karaniwang nag-iimbak ng isang circuit at ng mga halaga ng parameter nito (kung mayroon).SamplexItem, na karaniwang nag-iimbak ng mga sumusunod:- Isang template circuit
- Isang samplex object, na ginagamit para makabuo ng mga randomized na set ng parameter sa runtime (halimbawa para magsagawa ng twirling o mag-inject ng noise)
- Mga argumento para sa samplex, na maaaring magsama ng mga halaga ng parameter para sa orihinal na circuit
Ang bawat isa sa mga item na ito ay kumakatawan sa ibang gawain para isagawa ng Executor.
Bago ka magsimula
Ang ilang halimbawa ng code sa pahinang ito ay gumagamit ng samplex, na bahagi ng Samplomatic package. Samakatuwid, bago patakbuhin ang mga code block na iyon, kailangan mong i-install ang Samplomatic, tulad ng ipinapakita sa sumusunod na code block. Para sa karagdagang impormasyon, tingnan ang dokumentasyon ng Samplomatic.
pip install samplomatic
# For visualization support, include the visualization dependencies.
# pip install samplomatic[vis]
Halimbawa: Lumikha ng isang QuantumProgram na may dalawang magkaibang gawain
Una, i-initialize ang iyong quantum program, pagkatapos ay i-append ang mga program item sa pamamagitan ng paggamit ng alinman sa append_circuit_item o append_samplex_item (kung may samplex), tulad ng ipinapakita sa mga sumusunod na halimbawa.
Ang sumusunod na cell ay nag-i-initialize ng isang QuantumProgram at nagtatakda na dapat itong magpatakbo ng 1024 shot para sa bawat configuration ng bawat item sa program.
Hindi tulad ng Sampler, ang isang QuantumProgram ay tumatanggap lamang ng isang halaga ng shot. Kung gusto mo ng ibang halaga ng shot, kailangan mo ng hiwalay na QuantumProgram, na magiging isang hiwalay na job.
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)
Mag-append ng CircuitItem
Susunod, i-append ang target na circuit, na na-transpile ayon sa instruction set architecture (ISA) ng backend, sa QuantumProgram. Dahil ang circuit na ito ay may dalawang parameter, kailangan din naming magbigay ng mga halaga ng parameter (10 set sa halimbawang ito). Ang pagpapatakbo ng CircuitItem na ito ang unang gawain na isasagawa ng 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
)
Mag-append ng SamplexItem
Ang mga circuit item ay isinasagawa nang walang anumang uri ng randomization. Sa kabaligtaran, ang mga samplex item ay nagpapahintulot sa iyo na tukuyin kung paano gawing random ang kanilang nilalaman. Ang susunod na cell ay gumagamit ng function na generate_boxing_pass_manager() para grupuhin ang mga gate at measurement ng circuit sa mga box at magdagdag ng twirling annotation sa bawat box. Pagkatapos ay bumubuo ito ng pares ng template circuit at samplex gamit ang function na build().
Ang pagpapatakbo ng SamplexItem na ito ang pangalawang gawain na isasagawa ng program.
Tingnan ang dokumentasyon ng Samplomatic API para sa buong detalye tungkol sa samplex at ang mga argumento nito. Tingnan ang Gabay sa Transpiler ng Samplomatic para sa impormasyon tungkol sa paggamit ng function na 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()
Mga output
Ang output ng Executor ay isang QuantumProgramResult, na isang iterable. Naglalaman ito ng isang entry bawat input na QuantumProgramItem sa parehong pagkakasunod ng mga input item. Ang bawat isa sa mga output item na ito ay isang dictionary kung saan ang mga key ay mga string na tumutugma sa mga pangalan ng classical register sa mga input circuit (bukod sa iba pa), kaya hindi mo na kailangang kabisahin ang mga pangalan na ito tulad ng ginagawa mo sa output ng Sampler. Ang mga halaga ng dictionary ay may uri na np.ndarray.
Ang resulta para sa nakaraang halimbawa ay naglalaman ng mga item na ito:
Resulta ng CircuitItem
Ang unang item ay naglalaman ng mga resulta ng pagpapatakbo ng unang gawain (isang CircuitItem) sa program. Naglalaman ito ng isang key, meas, na siyang pangalan ng classical register sa input circuit. Ang halaga ng key na ito ay nagma-map sa isang np.ndarray na may hugis na (mga set ng parameter, mga shot, mga bit ng register), na (10, 1024, 3) para sa halimbawa sa itaas.
Ang sumusunod na code ay naglalarawan kung paano ma-access ang impormasyong ito:
# 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)
Resulta ng SamplexItem
Ang pangalawang item ay naglalaman ng mga resulta ng pagpapatakbo ng pangalawang gawain (isang SamplexItem) sa program. Ang item na ito ay naglalaman ng maraming key. Ang key na meas, na siyang pangalan ng classical register ng input circuit, ay nagma-map sa array ng mga resulta ng register na iyon. Ang array na ito ay may hugis na (mga randomization, mga set ng parameter, mga shot, mga classical bit), o (28, 10, 1024, 3) sa halimbawang ito. Bukod dito, ang output ay naglalaman ng key na measurement_flips.meas, na siyang mga pagwawasto ng bit-flip para i-undo ang measurement twirling para sa meas register. Ang hugis ng output na ito ay magiging (28, 10, 1, 3) para sa aming halimbawa dahil isang shot lamang ang kailangan para isagawa ang bit-flip.
# 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)
Mga susunod na hakbang
- I-explore ang mga halimbawa na gumagamit ng Executor.
- Matuto tungkol sa directed execution model.
- Unawain ang Executor broadcasting.