実行者の入出力
このページのコードは、以下の要件に基づいて開発されました。 これらのバージョン以降のご利用をお勧めします。
qiskit[all]~=2.4.0 qiskit-ibm-runtime~=0.46.1 samplomatic~=0.18.0
「Executor」プリミティブは、 指向型実行モデルの一部であり、エラー軽減ワークフローをカスタマイズする際により高い柔軟性を提供します。
Executorプリミティブの入出力は、Sampler プリミティブや Estimator プリミティブのそれとは大きく異なります。 QuantumProgramたとえば、Executorはパブのリストを入力として受け取るのではなく、オブジェクトの QuantumProgramItem リストを含むを受け取ります。 これらのコンテナクラスは、単純なタプルデータ構造である PUB よりも高い柔軟性を提供します。
QuantumProgramItem``QuantumProgramResult実行結果の出力はであり、これは反復可能オブジェクトであり、各入力に対して1つの要素を含みます。
入力:量子プログラム
QuantumProgram前述の通り、Executorプリミティブへの入力は、オブジェクトの
QuantumProgramItem 反復可能オブジェクトである。 これらのオブジェクトには、次の2つのタイプがあります:
CircuitItem…通常、回路とそのパラメータ値(ある場合)が格納されます。SamplexItem、通常は以下の内容を格納します:- 回路のテンプレート
- samplexオブジェクト。実行時にランダムなパラメータのセットを生成するために使用されます(たとえば、ツイリングの実行やノイズの注入など)
- samplexへの引数(元の回路のパラメータ値が含まれる場合がある)
これらの項目はそれぞれ、実行者が行うべき異なるタスクを表しています。
開始前に
samplexこのページにあるコード例の一部では、Samplomatic パッケージの一部である を使用しています。 したがって、これらのコードブロックを実行する前に、次のコードブロックに示すように、Samplomaticをインストールする必要があります。 詳細については、 Samplomaticのドキュメントを参照してください。
pip install samplomatic
# For visualization support, include the visualization dependencies.
# pip install samplomatic[vis]例:2つの異なるタスクを含む を作成 QuantumProgram する
まず量子プログラムを初期化し、次に以下の例に示すように、または append_samplex_item``append_circuit_item (samplexが存在する場合)を使用してプログラム項目を追加します。
次のセルでは、を QuantumProgram 初期化し、プログラム内の各項目のすべての構成について1024回の実行を行うよう指定しています。
Samplerとは異なり、t QuantumProgram は単一のショット値のみを受け取ります。 QuantumProgram別のショット値が必要な場合は、別途設定が必要となり、それは別の作業となります。
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)追加する CircuitItem
QuantumProgram次に、バックエンドの命令セットアーキテクチャ(ISA)に従ってトランスパイルされたターゲット回路を、.に追加します。 この回路には2つのパラメータがあるため、パラメータの値(この例では10組)も指定する必要があります。 これ CircuitItem を実行することが、プログラムが最初に行う処理です。
# 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
)追加する SamplexItem
回路内の項目は、いかなるランダム化も行わずに実行されます。 それどころか、samplexアイテムでは、コンテンツをどのようにランダム化するかを指定することができます。 次のセルでは、関数を使用して generate_boxing_pass_manager() 回路のゲートと測定値をボックスにまとめ、各ボックスに回転する注釈を追加します。 その後、この build() 関数を使用して、テンプレート回路とサンプルクス・ペアを生成します。
これ SamplexItem を実行するのは、プログラムが実行する2番目のタスクです。
およびその引数に関する samplex 詳細については、Samplomatic API ドキュメントを参照してください。 関 generate_boxing_pass_manager() 数の使用方法については、『Samplomatic Transpiler ガイド 』を参照してください。
# 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())Output:
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()出力
QuantumProgramResultExecutor の出力は、反復可能なオブジェクトである。 入力 QuantumProgramItem 項目ごとに1つのエントリが含まれており、入力項目の順序と同じ順序で並んでいます。 これらの出力項目のそれぞれは辞書であり、そのキーは(とりわけ)入力回路における従来のレジスタ名に対応する文字列となっています。そのため、Samplerの出力の場合のように、これらの名前を覚える必要はもうありません。 np.ndarray辞書の値は 型です。
前の例の結果には、以下の項目が含まれています:
CircuitItem の結果
CircuitItem最初の項目には、プログラム内の最初のタスク(a)を実行した結果が含まれています。 measここには、入力回路における古典的なレジスタの名前である「」という単一のキーが含まれています。 (parameter sets, shots, register bits)このキーの値は、形状が の配列 np.ndarray にマッピングされます。上記の例では、その形状は (10, 1024, 3) となります。
以下のコードは、この情報にアクセスする方法を示しています:
# Access the results of the classical register of task #0, a CircuitItem
result_0 = result[0]["meas"]
print(f"Result shape: {result_0.shape}")Output:
Result shape: (10, 1024, 3)
SamplexItem の結果
SamplexItem2番目の項目には、プログラム内の2番目のタスク(a)を実行した結果が含まれています。 このアイテムには複数のキーが含まれています。 key(入力回路の古典的レジスタの名前)は meas 、そのレジスタの結果の配列に対応付けられます。 (randomizations, parameter sets, shots, classical bits)この配列の次元は、この例では (28, 10, 1024, 3) です。 measurement_flips.meas さらに、出力には キーが含まれており、これは レジスタの meas 測定によるビット反転を元に戻すための補正値です。 この例の場合、ビット反転を行うのに1ショットしか必要としないため、出力形状は(28, 10, 1, 3)となります。
# 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_1Output:
Result shape: (28, 10, 1024, 3)
Bit-flip corrections shape: (28, 10, 1, 3)
次のステップ
- Executor を使用した例をご覧ください。
- 指向型実行モデルについて学びましょう。
- 「Executor」のブロードキャストについて理解する。