Qiskit SDK プリミティブを用いた正確なシミュレーション
このページのコードは、以下の要件に基づいて開発された。 これらのバージョンまたは新しいバージョンの使用をお勧めします。
qiskit[all]~=2.5.1
Qiskit SDK に含まれる参照プリミティブは、局所的な状態ベクトルシミュレーションを実行します。 これらのシミュレーションでは、 デバイスのノイズをモデル化することはできませんが、より高度なシミュレーション 手法( Qiskit Aerの使用 )を検討したり、実デバイス上で実行したり( IBM Quantum プリミティブ )する前に、アルゴリズムの迅速なプロトタイピングを行う上で役立ちます。
Estimatorプリミティブは回路の期待値を計算することができ、Samplerプリミティブは回路の出力分布からサンプリングすることができる。 プリミティブは回路の出力分布から
以下のセクションでは、参照プリミティブを使用してワークフローをローカルで実行する方法を示します。
参照用見積もりツールを使用する
qiskit.primitives 、ローカルの状態ベクトル・シミュレータ上で動作する EstimatorV2 。 シミュレータは StatevectorEstimator クラスである。 回路、観測値、パラメータを入力とし、局所的に計算された期待値を返す。
以下のコードは、これから紹介する例で使用する入力データを準備するものです。 オブザーバブルの
期待される入力型は です qiskit.quantum_info.SparsePauliOp。 なお、
この例の回路はパラメータ化されていますが、パラメータ化されていない回路に対してもEstimatorを実行することができます。
Estimator に渡される回路には、 測定値を含めないでください。
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
# circuit for which you want to obtain the expected value
circuit = QuantumCircuit(2)
circuit.ry(Parameter("theta"), 0)
circuit.h(0)
circuit.cx(0, 1)
circuit.draw("mpl", style="iqp")Output:
from qiskit.quantum_info import SparsePauliOp
import numpy as np
# observable(s) whose expected values you want to compute
observable = SparsePauliOp(["II", "XX", "YY", "ZZ"], coeffs=[1, 1, -1, 1])
# value(s) for the circuit parameter(s)
parameter_values = [[0], [np.pi / 6], [np.pi / 2]]IBM Quantum プリミティブのワークフローでは、回路およびオブザーバブルを、QPUがサポートする命令のみを使用するように変換する必要があります(これを「 命令セットアーキテクチャ(ISA) 回路およびオブザーバブル」と呼びます)。 参照プリミティブは、ローカルな状態ベクトルのシミュレーションに依存しているため、依然として抽象的な命令を受け付けますが、回路のトランスパイルを行うことは、回路の最適化という観点からは依然として有益である可能性があります。
# Generate a pass manager without providing a backend
from qiskit.transpiler import generate_preset_pass_manager
pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit = pm.run(circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)推定器を初期化する
をインスタンス化する。 qiskit.primitives.StatevectorEstimator.
from qiskit.primitives import StatevectorEstimator
estimator = StatevectorEstimator()走って結果を出せ
この例では QuantumCircuitと 観測可能です。
を呼び出して推定を実行する。 StatevectorEstimator.run オブジェクトのインスタンスを返す PrimitiveJob オブジェクトのインスタンスを返します。 ジョブから(オブジェクトとして)結果を得ることができます。 qiskit.primitives.PrimitiveResult オブジェクトとして) オブジェクトとして qiskit.primitives.PrimitiveJob.result メソッドで取得できます。
job = estimator.run([(circuit, observable, parameter_values)])
result = job.result()
print(f" > Result class: {type(result)}")Output:
> Result class: <class 'qiskit.primitives.containers.primitive_result.PrimitiveResult'>
結果から期待値を取得する
プリミティブの結果はオブジェクト PubResult の配列を出力し、配列の各要素は PUB 内のすべての回路-観測可能な組み合わせに対応する評価の配列をデータに含むオブジェクト PubResult である。
最初の(そしてこの場合は唯一の)回路評価の期待値とメタデータを取得するには、評価にアクセスする必要があります。 data にアクセスする必要があります。 PUB 0:
print(f" > Expectation value: {result[0].data.evs}")
print(f" > Metadata: {result[0].metadata}")Output:
> Expectation value: [4. 3.73205081 2. ]
> Metadata: {'target_precision': 0.0, 'circuit_metadata': {}}
セット推定器の実行オプションを設定する
デフォルトでは、リファレンス・エスティメータは quantum_info.Statevector クラスを使用します。
しかし、これはサンプリング・オーバーヘッド(「ショット・ノイズ」とも呼ばれる)の影響を導入するために修正することができる。
Estimatorは precision 。 プリミティブの実装が期待値の推定に目標とすべきエラーバーを表します。 これはサンプリングのオーバーヘッドで、 .run() メソッドでのみ定義されている。 これにより、 PUB レベルまでオプションを微調整できる。
# Estimate expectation values for two PUBs, both with 0.05 precision.
precise_job = estimator.run(
[(circuit, observable, parameter_values)], precision=0.05
)完全な例については、 「Estimator」のサンプルページをご覧ください。
参照サンプラーを使用する
qiskit.primitives における SamplerV2 の参照実装は StatevectorSampler クラスである。 回路とパラメータを入力とし、出力確率分布からサンプリングした結果を出力状態の準確率分布として返す。
以下のコードは、以降の例で使用される入力データを準備するものです。 なお、 これらの例では単一のパラメータ化された回路を実行していますが、 パラメータ化されていない回路でもSamplerを実行することができます。
from qiskit import QuantumCircuit
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
circuit.draw("mpl", style="iqp")Output:
サンプラーに渡される量子回路には、測定値が含まれていなければならない。
IBM Quantum プリミティブのワークフローでは、回路を、QPUがサポートする命令のみを使用するように変換する必要があります(これを「ISA回路」と呼びます)。 参照プリミティブは、ローカルな状態ベクトルのシミュレーションに依存しているため、依然として抽象的な命令を受け付けますが、回路のトランスパイルを行うことは、回路の最適化という観点からは依然として有益である可能性があります。
# Generate a pass manager without providing a backend
from qiskit.transpiler import generate_preset_pass_manager
pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit = pm.run(qc)初期化 SamplerV2
インスタンス qiskit.primitives.StatevectorSampler:
from qiskit.primitives import StatevectorSampler
sampler = StatevectorSampler()走って結果を出せ
# execute 1 circuit with Sampler
job = sampler.run([circuit])
pub_result = job.result()[0]
print(f" > Result class: {type(pub_result)}")Output:
> Result class: <class 'qiskit.primitives.containers.sampler_pub_result.SamplerPubResult'>
プリミティブは複数のPUBを入力として受け入れ、 PUB、それぞれ独自の結果を得る。 したがって、さまざまなパラメータと観測値の組み合わせで異なる回路を実行し、 PUB :
from qiskit.transpiler import generate_preset_pass_manager
# create two circuits
circuit1 = circuit.copy()
circuit2 = circuit.copy()
# transpile circuits
pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit1 = pm.run(circuit1)
isa_circuit2 = pm.run(circuit2)
# execute 2 circuits using Sampler
job = sampler.run([(isa_circuit1), (isa_circuit2)])
pub_result_1 = job.result()[0]
pub_result_2 = job.result()[1]
print(f" > Result class: {type(pub_result)}")Output:
> Result class: <class 'qiskit.primitives.containers.sampler_pub_result.SamplerPubResult'>
確率分布または測定結果を取得する
測定結果のサンプルは、 ビット列またはカウントとして返される。 ビット列は、測定されたショット順を保ったまま、測定結果を示している。 サンプラーの結果オブジェクトは、ダイナミック回路との互換性を保つため、入力回路の古典的なレジスタ名でデータを整理する。
クラシック・レジスタの名前のデフォルトは "meas"。 この名前は、あとで計測ビット列にアクセスするときに使う。
# Define quantum circuit with 2 qubits
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
circuit.draw()Output:
┌───┐ ░ ┌─┐
q_0: ┤ H ├──■───░─┤M├───
└───┘┌─┴─┐ ░ └╥┘┌─┐
q_1: ─────┤ X ├─░──╫─┤M├
└───┘ ░ ║ └╥┘
meas: 2/══════════════╩══╩═
0 1
# Transpile circuit
pm = generate_preset_pass_manager(optimization_level=1)
isa_circuit = pm.run(circuit)
# Run using Sampler
result = sampler.run([circuit]).result()
# Access result data for PUB 0
data_pub = result[0].data
# Access bitstring for the classical register "meas"
bitstrings = data_pub.meas.get_bitstrings()
print(f"The number of bitstrings is: {len(bitstrings)}")
# Get counts for the classical register "meas"
counts = data_pub.meas.get_counts()
print(f"The counts are: {counts}")Output:
The number of bitstrings is: 1024
The counts are: {'00': 538, '11': 486}
実行オプションを変更する
デフォルトでは、リファレンス・サンプラーは quantum_info.Statevector クラス。
しかし、これはサンプリング・オーバーヘッド(「ショット・ノイズ」とも呼ばれる)の影響を導入するために修正することができる。 このオーバーヘッドを管理するために、サンプラーインターフェイスは PUB レベルで定義できる shots 引数を受け付ける。
この例では、2つの回路を定義したと仮定しています。
# Sample two circuits at 128 shots each.
sampler.run([isa_circuit1, isa_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([(isa_circuit1, None, 123), (isa_circuit2, None, 456)])Output:
<qiskit.primitives.primitive_job.PrimitiveJob at 0x7f94d59db010>
完全な例については、 「Sampler」のサンプルページをご覧ください。
次のステップ
- より大規模な回路を扱える、より高性能なシミュレーションや、シミュレーションにノイズモデルを組み込むには、 Qiskit Aerプリミティブによる正確でノイズの少ないシミュレーションを参照してください。
- シミュレーションにQuantum Composerを使用する方法については、 IBM Quantum Composer ガイドを参照してください。
- Qiskit Estimator API リファレンスをお読みください。
- Qiskit Sampler API リファレンスをお読みください。