อินพุตและเอาต์พุตของ Primitives
beta release ของโมเดลการประมวลผลใหม่พร้อมให้ใช้งานแล้ว โมเดล directed execution ให้ความยืดหยุ่นมากขึ้น ในการปรับแต่ง error mitigation workflow ดูคู่มือ Directed execution model สำหรับข้อมูลเพิ่มเติม
Package versions
The code on this page was developed using the following requirements. We recommend using these versions or newer.
qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
หน้านี้ให้ภาพรวมของอินพุตและเอาต์พุตของ Qiskit Runtime primitives ที่ประมวลผล workloads บน IBM Quantum® compute resources Primitives เหล่านี้ช่วยให้สามารถกำหนด vectorized workloads ได้อย่างมีประสิทธิภาพโดยใช้โครงสร้างข้อมูลที่เรียกว่า Primitive Unified Bloc (PUB) PUBs เหล่านี้คือหน่วยงานพื้นฐานที่ QPU ต้องใช้ในการประมวลผล workloads และใช้เป็นอินพุตของเมธอด run() สำหรับ Sampler และ Estimator primitives ซึ่งประมวลผล workload ที่กำหนดเป็น job จากนั้น หลังจาก job เสร็จสิ้น ผลลัพธ์จะถูกส่งคืนในรูปแบบที่ขึ้นอยู่กับทั้ง PUBs ที่ใช้และ runtime options ที่ระบุจาก Sampler หรือ Estimator primitives
ภาพรวมของ PUBs
เมื่อเรียกใช้เมธอด run() ของ primitive argument หลักที่ต้องใช้คือ list ของ tuple หนึ่งตัวหรือมากกว่า — หนึ่ง tuple ต่อหนึ่ง circuit ที่รัน แต่ละ tuple นี้ถือเป็น PUB และ elements ที่จำเป็นของแต่ละ tuple ในรายการขึ้นอยู่กับ primitive ที่ใช้ ข้อมูลที่ระบุใน tuples เหล่านี้ยังสามารถจัดเรียงในรูปแบบต่างๆ เพื่อให้มีความยืดหยุ่นใน workload ผ่านการ broadcasting — ซึ่งมีกฎที่อธิบายไว้ในส่วนถัดไป
Estimator PUB
สำหรับ Estimator primitive รูปแบบของ PUB ควรมีค่าไม่เกินสี่ค่า:
QuantumCircuitเดียว ซึ่งอาจมีParameterobjects หนึ่งตัวหรือมากกว่า- รายการของ observables หนึ่งตัวหรือมากกว่า ซึ่งระบุ expectation values ที่ต้องการประมาณ จัดเรียงเป็น array (เช่น observable เดียวแทนด้วย 0-d array, รายการของ observables เป็น 1-d array และอื่นๆ) ข้อมูลสามารถอยู่ในรูปแบบ
ObservablesArrayLikeใดก็ได้ เช่นPauli,SparsePauliOp,PauliListหรือstrหมายเหตุถ้ามี observables สองตัวที่ commute กันอยู่ใน PUBs ต่างกันแต่มี circuit เดียวกัน จะไม่ถูกประมาณด้วยการวัดเดียวกัน แต่ละ PUB แทน basis สำหรับการวัดที่แตกต่างกัน ดังนั้นจึงต้องมีการวัดแยกกันสำหรับแต่ละ PUB เพื่อให้แน่ใจว่า commuting observables ถูกประมาณด้วยการวัดเดียวกัน ต้องจัดกลุ่มไว้ใน PUB เดียวกัน
- ชุดของค่า parameter เพื่อ bind กับ circuit สามารถระบุเป็น array-like object เดียวที่ index สุดท้ายอยู่บน
Parameterobjects ของ circuit หรือละไว้ (หรือเทียบเท่ากับการตั้งค่าเป็นNone) ถ้า circuit ไม่มีParameterobjects - (ไม่บังคับ) ความแม่นยำเป้าหมายสำหรับ expectation values ที่ต้องการประมาณ
Sampler PUB
สำหรับ Sampler primitive รูปแบบของ PUB tuple มีค่าไม่เกินสามค่า:
QuantumCircuitเดียว ซึ่งอาจมีParameterobjects หนึ่งตัวหรือมากกว่า หมายเหตุ: Circuit เหล่านี้ควรมีคำสั่งการวัดสำหรับแต่ละ qubit ที่ต้องการ sample ด้วย- ชุดของค่า parameter เพื่อ bind กับ circuit (จำเป็นเฉพาะเมื่อมี
Parameterobjects ที่ต้อง bind ตอน runtime) - (ไม่บังคับ) จำนวน shots สำหรับวัด circuit
โค้ดต่อไปนี้แสดงตัวอย่างชุดของ vectorized inputs ให้กับ Estimator primitive และรันบน IBM® backend เป็น RuntimeJobV2 object เดียว
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-ibm-runtime
from qiskit.circuit import (
Parameter,
QuantumCircuit,
ClassicalRegister,
QuantumRegister,
)
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives.containers import BitArray
from qiskit_ibm_runtime import (
QiskitRuntimeService,
EstimatorV2 as Estimator,
SamplerV2 as Sampler,
)
import numpy as np
# Instantiate runtime service and get
# the least busy backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
# Define a circuit with two parameters.
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.ry(Parameter("a"), 0)
circuit.rz(Parameter("b"), 0)
circuit.cx(0, 1)
circuit.h(0)
# Transpile the circuit
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
transpiled_circuit = pm.run(circuit)
layout = transpiled_circuit.layout
# Now define a sweep over parameter values, the last axis of dimension 2 is
# for the two parameters "a" and "b"
params = np.vstack(
[
np.linspace(-np.pi, np.pi, 100),
np.linspace(-4 * np.pi, 4 * np.pi, 100),
]
).T
# Define three observables. The inner length-1 lists cause this array of
# observables to have shape (3, 1), rather than shape (3,) if they were
# omitted.
observables = [
[SparsePauliOp(["XX", "IY"], [0.5, 0.5])],
[SparsePauliOp("XX")],
[SparsePauliOp("IY")],
]
# Apply the same layout as the transpiled circuit.
observables = [
[observable.apply_layout(layout) for observable in observable_set]
for observable_set in observables
]
# Estimate the expectation value for all 300 combinations of observables
# and parameter values, where the pub result will have shape (3, 100).
#
# This shape is due to our array of parameter bindings having shape
# (100, 2), combined with our array of observables having shape (3, 1).
estimator_pub = (transpiled_circuit, observables, params)
# Instantiate the new estimator object, then run the transpiled circuit
# using the set of parameters and observables.
estimator = Estimator(mode=backend)
job = estimator.run([estimator_pub])
result = job.result()
กฎการ Broadcasting
PUBs รวม elements จาก arrays หลายตัว (observables และค่า parameter) โดยทำตามกฎการ broadcasting เดียวกับ NumPy ส่วนนี้สรุปกฎเหล่านั้นโดยย่อ สำหรับคำอธิบายโดยละเอียด ดูเอกสาร NumPy broadcasting rules
กฎ:
- Input arrays ไม่จำเป็นต้องมีจำนวน dimensions เท่ากัน
- Array ผลลัพธ์จะมีจำนวน dimensions เท่ากับ input array ที่มี dimension ใหญ่ที่สุด
- ขนาดของแต่ละ dimension คือขนาดที่ใหญ่ที่สุดของ dimension ที่ตรงกัน
- Dimensions ที่หายไปถือว่ามีขนาดหนึ่ง
- การเปรียบเทียบ shape เริ่มจาก dimension ขวาสุด และดำเนินต่อไปทางซ้าย
- Dimensions สองตัวเข้ากันได้ถ้าขนาดเท่ากันหรือถ้าตัวหนึ่งเป็น 1
ตัวอย่างคู่ของ arrays ที่ broadcast ได้:
A1 (1d array): 1
A2 (2d array): 3 x 5
Result (2d array): 3 x 5
A1 (3d array): 11 x 2 x 7
A2 (3d array): 11 x 1 x 7
Result (3d array): 11 x 2 x 7
ตัวอย่างคู่ของ arrays ที่ broadcast ไม่ได้:
A1 (1d array): 5
A2 (1d array): 3
A1 (2d array): 2 x 1
A2 (3d array): 6 x 5 x 4 # This would work if the middle dimension were 2, but it is 5.
EstimatorV2 คืน expectation value estimate หนึ่งค่าสำหรับแต่ละ element ของ shape ที่ broadcast แล้ว
นี่คือตัวอย่างของ patterns ทั่วไปที่แสดงในรูปของ array broadcasting พร้อมกับการแสดงภาพแบบ visual ในรูปถัดไป:
ชุดค่า parameter แทนด้วย n x m arrays และ observable arrays แทนด้วย single-column arrays หนึ่งตัวหรือมากกว่า สำหรับแต่ละตัวอย่างในโค้ดก่อนหน้า ชุดค่า parameter ถูกรวมกับ observable array เพื่อสร้าง expectation value estimates ที่ได้
-
ตัวอย่างที่ 1: (broadcast single observable) มีชุดค่า parameter เป็น array 5x1 และ observables array แบบ 1x1 item เดียวใน observables array ถูกรวมกับแต่ละ item ในชุดค่า parameter เพื่อสร้าง array 5x1 เดียวที่แต่ละ item เป็นการรวมกันของ item ต้นฉบับในชุดค่า parameter กับ item ใน observables array
-
ตัวอย่างที่ 2: (zip) มีชุดค่า parameter 5x1 และ observables array 5x1 ผลลัพธ์คือ array 5x1 ที่แต่ละ item เป็นการรวมกันของ item ที่ n ในชุดค่า parameter กับ item ที่ n ในชุด observables array
-
ตัวอย่างที่ 3: (outer/product) มีชุดค่า parameter 1x6 และ observables array 4x1 การรวมกันของพวกมันให้ผล array 4x6 ที่สร้างโดยการรวมแต่ละ item ในชุดค่า parameter กับ ทุก item ใน observables array ดังนั้นแต่ละค่า parameter จึงกลายเป็นคอลัมน์ทั้งคอลัมน์ในผลลัพธ์
-
ตัวอย่างที่ 4: (Standard nd generalization) มีชุดค่า parameter array 3x6 และ observables array สองตัวแบบ 3x1 พวกมันรวมกันเพื่อสร้าง output arrays 3x6 สองตัวในลักษณะเดียวกับตัวอย่างก่อนหน้า
# Broadcast single observable
parameter_values = np.random.uniform(size=(5,)) # shape (5,)
observables = SparsePauliOp("ZZZ") # shape ()
# >> pub result has shape (5,)
# Zip
parameter_values = np.random.uniform(size=(5,)) # shape (5,)
observables = [
SparsePauliOp(pauli) for pauli in ["III", "XXX", "YYY", "ZZZ", "XYZ"]
] # shape (5,)
# >> pub result has shape (5,)
# Outer/Product
parameter_values = np.random.uniform(size=(1, 6)) # shape (1, 6)
observables = [
[SparsePauliOp(pauli)] for pauli in ["III", "XXX", "YYY", "ZZZ"]
] # shape (4, 1)
# >> pub result has shape (4, 6)
# Standard nd generalization
parameter_values = np.random.uniform(size=(3, 6)) # shape (3, 6)
observables = [
[
[SparsePauliOp(["XII"])],
[SparsePauliOp(["IXI"])],
[SparsePauliOp(["IIX"])],
],
[
[SparsePauliOp(["ZII"])],
[SparsePauliOp(["IZI"])],
[SparsePauliOp(["IIZ"])],
],
] # shape (2, 3, 1)
# >> pub result has shape (2, 3, 6)
แต่ละ SparsePauliOp นับเป็น element เดียวในบริบทนี้ โดยไม่คำนึงถึงจำนวน Paulis ที่มีอยู่ใน SparsePauliOp ดังนั้น สำหรับจุดประสงค์ของกฎ broadcasting เหล่านี้ elements ต่อไปนี้ทั้งหมดมี shape เดียวกัน:
a = SparsePauliOp("Z") # shape ()
b = SparsePauliOp("IIIIZXYIZ") # shape ()
c = SparsePauliOp.from_list(["XX", "XY", "IZ"]) # shape ()
รายการของ operators ต่อไปนี้ แม้จะเทียบเท่ากันในแง่ของข้อมูลที่มีอยู่ มี shape ต่างกัน:
list1 = SparsePauliOp.from_list(["XX", "XY", "IZ"]) # shape ()
list2 = [SparsePauliOp("XX"), SparsePauliOp("XY"), SparsePauliOp("IZ")] # shape (3, )