Skip to main content
IBM Quantum Platform

プリミティブ

qiskit.primitives

プリミティブは、プリミティブ・ユニファイド・ブロック(PUB)と呼ばれる入力ユニットが、効率的に出力を生成するために量子リソースを必要とする、より大規模なアプリケーションで使用される計算ビルディングブロックである。

BaseEstimatorV2現在、2種類のプリミティブが存在し、それらの最新バージョンにおける抽象化は、およびによって BaseSamplerV2 定義されている。 サンプラーは、量子回路(またはパラメータ化された回路における値のスイープ)を受け入れ、その古典的な出力レジスタからサンプリングを行う役割を担っています。 推定器は、回路と観測量の組み合わせ(またはそのスイープ)を受け入れ、観測量の期待値を推定する。

Qiskit では、これらの抽象化それぞれについて、および StatevectorEstimator クラス StatevectorSampler においてリファレンス実装を提供しています。

BaseEstimatorV1サンプラーおよび推定器の抽象化の以前のバージョンは、およびによって BaseSamplerV1 定義されています。 BaseEstimatorV2これらのインターフェースは、この run メソッドに対して異なる、かつ柔軟性に欠ける入出力形式を採用しており、実際には および に BaseSamplerV2 ほぼ置き換えられています。 ただし、下位互換性を確保するため、元の抽象インターフェースの定義はそのまま残されています。 V1 と V2 の違いに関する詳細については、このページの「移行」セクションをご確認ください。


EstimatorV2 の概要

BaseEstimatorV2 これは、指定された量子回路と観測量の組み合わせについて、期待値を推定するプリミティブです。

構築後、パブ(Primitive Unified Blocs)のリストを引数としてその run() メソッドを呼び出すことで、見積もり器が使用されます。 各パブには3つの値が含まれており、これらが組み合わさって、推定器が完了すべき計算単位を定義します:

  • 単一の QuantumCircuit(パラメータ化される可能性のある)関数であり、その最終状態を ψ(θ)\psi(\theta) と定義する
  • strPauli推定対象となる期待値を指定する1つ以上の観測量(任意の ObservablesArrayLike、 を含む、 SparsePauliOp などとして指定されるもの)。これらは HjH_j と表記され、
  • 回路をバインドするためのパラメータ値セットのコレクション、 θk\theta_k

推定関数を実行すると オブジェクトが BasePrimitiveJob 返され、そのメソッド result() を呼び出すと、各パブに対する期待値の推定値とメタデータが得られます:

ψ(θk)Hjψ(θk)\langle\psi(\theta_k)|H_j|\psi(\theta_k)\rangle

パブの観測値とパラメータ値の部分は、標準的なブロードキャストルールが適用される任意の次元の配列値であることができ、その結果、各パブの推定結果も一般的に配列値である。 詳しくはこちらをご覧ください。

以下は推定値の使用例である。

from qiskit.primitives import StatevectorEstimator as Estimator
from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp

psi1 = RealAmplitudes(num_qubits=2, reps=2)
psi2 = RealAmplitudes(num_qubits=2, reps=3)

H1 = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
H2 = SparsePauliOp.from_list([("IZ", 1)])
H3 = SparsePauliOp.from_list([("ZI", 1), ("ZZ", 1)])

theta1 = [0, 1, 1, 2, 3, 5]
theta2 = [0, 1, 1, 2, 3, 5, 8, 13]
theta3 = [1, 2, 3, 4, 5, 6]

estimator = Estimator()

# calculate [ <psi1(theta1)|H1|psi1(theta1)> ]
job = estimator.run([(psi1, H1, [theta1])])
job_result = job.result() # It will block until the job finishes.
print(f"The primitive-job finished with result {job_result}")

# calculate [ [<psi1(theta1)|H1|psi1(theta1)>,
#              <psi1(theta3)|H3|psi1(theta3)>],
#             [<psi2(theta2)|H2|psi2(theta2)>] ]
job2 = estimator.run(
    [
        (psi1, [H1, H3], [theta1, theta3]),
        (psi2, H2, theta2)
    ],
    precision=0.01
)
job_result = job2.result()
print(f"The primitive-job finished with result {job_result}")

SamplerV2 の概要

BaseSamplerV2 量子回路の出力をサンプリングするプリミティブである。

構築後、パブ(Primitive Unified Blocs)のリストを引数としてその run() メソッドを呼び出すことで、サンプラーを使用します。 各パブには、それらが組み合わさることで、サンプラーが完了すべき計算単位を定義する値が含まれています:

  • 単一の QuantumCircuitパラメータ化されていることもある。
  • 回路がパラメトリックである場合にバインドするコレクション・パラメータ値セット。
  • オプションとして、サンプリングするショット数(設定されていない場合は、ランメソッドで決定される)。

sampler を実行すると オブジェクトが BasePrimitiveJob 返され、そのメソッド result() を呼び出すと、各 pub に対する出力サンプルとメタデータが得られます。

サンプラーの使用例を紹介しよう。

from qiskit.primitives import StatevectorSampler as Sampler
from qiskit import QuantumCircuit
from qiskit.circuit.library import RealAmplitudes

# create a Bell circuit
bell = QuantumCircuit(2)
bell.h(0)
bell.cx(0, 1)
bell.measure_all()

# create two parameterized circuits
pqc = RealAmplitudes(num_qubits=2, reps=2)
pqc.measure_all()
pqc2 = RealAmplitudes(num_qubits=2, reps=3)
pqc2.measure_all()

theta1 = [0, 1, 1, 2, 3, 5]
theta2 = [0, 1, 2, 3, 4, 5, 6, 7]

# initialization of the sampler
sampler = Sampler()

# collect 128 shots from the Bell circuit
job = sampler.run([bell], shots=128)
job_result = job.result()
print(f"The primitive-job finished with result {job_result}")

# run a sampler job on the parameterized circuits
job2 = sampler.run([(pqc, theta1), (pqc2, theta2)])
job_result = job2.result()
print(f"The primitive-job finished with result {job_result}")

EstimatorV1 の概要

現在、Qiskit にはレガシーインターフェースの実装は EstimatorV1 存在しません。 ただし、外部の実装との下位互換性を確保するため、からの BaseEstimatorV1 抽象インターフェースの定義は、依然としてこのパッケージの一部となっています。

実装は EstimatorV1 、空のパラメータセットで初期化されます。 BaseEstimatorV1 以下のパラメータを指定して、この .run() メソッドを呼び出すことができます:

  • 量子回路 ( ψi(θ)\psi_i(\theta) ): (パラメータ化された)量子回路のリスト(オブジェクトのリスト)。 QuantumCircuit オブジェクトのリスト)。
  • オブザーバブル( HjH_j ):オブジェクトの SparsePauliOp リスト。
  • パラメータ値 ( θk\theta_k ): 量子回路のパラメータに束縛される値の集合のリスト(浮動小数点数のリスト)。

このメソッドは オブジェクトを JobV1 返す必要があります。 この関数を呼び出す qiskit.providers.JobV1.result() と、期待値のリストに加え、推定値の信頼区間などのオプションのメタデータが返されます。

ψi(θk)Hjψi(θk)\langle\psi_i(\theta_k)|H_j|\psi_i(\theta_k)\rangle

以下は、 EstimatorV1 の実装例である。 Qiskitには現在、レガシーな EstimatorV1 インターフェイスの実装がないことに注意してください。

# This is a fictional import path.
# There are currently no EstimatorV1 implementations in Qiskit.
from estimator_v1_location import EstimatorV1
from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp

psi1 = RealAmplitudes(num_qubits=2, reps=2)
psi2 = RealAmplitudes(num_qubits=2, reps=3)

H1 = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
H2 = SparsePauliOp.from_list([("IZ", 1)])
H3 = SparsePauliOp.from_list([("ZI", 1), ("ZZ", 1)])

theta1 = [0, 1, 1, 2, 3, 5]
theta2 = [0, 1, 1, 2, 3, 5, 8, 13]
theta3 = [1, 2, 3, 4, 5, 6]

estimator = EstimatorV1()

# calculate [ <psi1(theta1)|H1|psi1(theta1)> ]
job = estimator.run([psi1], [H1], [theta1])
job_result = job.result() # It will block until the job finishes.
print(f"The primitive-job finished with result {job_result}")

# calculate [ <psi1(theta1)|H1|psi1(theta1)>,
#             <psi2(theta2)|H2|psi2(theta2)>,
#             <psi1(theta3)|H3|psi1(theta3)> ]
job2 = estimator.run(
    [psi1, psi2, psi1],
    [H1, H2, H3],
    [theta1, theta2, theta3]
)
job_result = job2.result()
print(f"The primitive-job finished with result {job_result}")

SamplerV1 の概要

現在、Qiskit にはレガシーインターフェースの実装は SamplerV1 存在しません。 ただし、外部実装との下位互換性を確保するため、からの BaseSamplerV1 抽象インターフェース定義は依然としてこのパッケージの一部となっています。

サンプラークラスは、量子回路からビット列の確率または準確率を計算する。

A SamplerV1 は、空のパラメータセットで初期化されます。 BaseSamplerV1 実装は、以下のパラメータを指定して メソッドを .run() 介して呼び出すことができます:

  • quantum circuits ( ψi(θ)\psi_i(\theta) ): (パラメータ化された)量子回路のリスト。 (オブジェクトのリスト QuantumCircuit オブジェクトのリスト)
  • parameter values ( θk\theta_k ): 量子回路のパラメータに束縛されるパラメータ値のセットのリスト。 (フロートのリストのリスト)

.run() オブジェクトを JobV1 返します。 この関数を呼び出す qiskit.providers.JobV1.result() と、ビット列の確率または準確率に加え、サンプル内の誤差範囲などのオプションのメタデータを含むオブジェクトが SamplerResult 返されます。

以下は、 SamplerV1 の実装例である。 Qiskitには現在、レガシーな SamplerV1 インターフェイスの実装がないことに注意してください。

# This is a fictional import path.
# There are currently no SamplerV1 implementations in Qiskit.
from sampler_v1_location import Sampler
from qiskit import QuantumCircuit
from qiskit.circuit.library import RealAmplitudes

# a Bell circuit
bell = QuantumCircuit(2)
bell.h(0)
bell.cx(0, 1)
bell.measure_all()

# two parameterized circuits
pqc = RealAmplitudes(num_qubits=2, reps=2)
pqc.measure_all()
pqc2 = RealAmplitudes(num_qubits=2, reps=3)
pqc2.measure_all()

theta1 = [0, 1, 1, 2, 3, 5]
theta2 = [0, 1, 2, 3, 4, 5, 6, 7]

# initialization of the sampler
sampler = SamplerV1()

# Sampler runs a job on the Bell circuit
job = sampler.run(
    circuits=[bell], parameter_values=[[]], parameters=[[]]
)
job_result = job.result()
print([q.binary_probabilities() for q in job_result.quasi_dists])

# Sampler runs a job on the parameterized circuits
job2 = sampler.run(
    circuits=[pqc, pqc2],
    parameter_values=[theta1, theta2],
    parameters=[pqc.parameters, pqc2.parameters])
job_result = job2.result()
print([q.binary_probabilities() for q in job_result.quasi_dists])

プリミティブからの移行 V1 から V2 へ

Primitives V1 と V2 のAPIにおける形式的な違いは、プリミティブの実装が継承する基底クラスにあり、これらはすべてページの下部に一覧表示されています。 ただし、概念的なレベルでは、 V1 から V2: へ移行する際に留意すべき、いくつかの重要な違いがあります

  1. V2 プリミティブはベクトル化された入力を好み、単一の回路をベクトル値(またはより一般的には配列値)の仕様でグループ化することができる。 各グループはプリミティブ・ユニファイド・ブロック(パブ)と呼ばれ、各パブは独自の結果を得る。 例えば、見積もりでは次のような違いを比較することができる:

    # Favoured V2 pattern. There is only one pub here, but there could be more.
    job = estimator_v2.run([(circuit, [obs1, obs2, obs3, obs4])])
    evs = job.result()[0].data.evs
    
    # V1 equivalent, where the same circuit must be provided four times.
    job = estimator_v1.run([circuit] * 4, [obs1, obs2, obs3, obs4])
    evs = job.result().values

    上記の例では、簡潔にするために示していないが、回路はパラメトリックにすることができ、観測値の配列に対してパラメータ値の配列がブロードキャストされる。 サンプラーも同様だが、観測値がない:

    # Favoured V2 pattern. There is only one pub here, but there could be more.
    job = sampler_v2.run([(circuit, [vals1, vals2, vals3])])
    samples = job.result()[0].data
    
    # V1 equivalent, where the same circuit must be provided three times.
    sampler_v1.run([circuit] * 3, [vals1, vals2, vals3])
    quasi_dists = job.result().quasi_dists
  2. V2 サンプラーは、古典的な結果のサンプルを、それらが測定されたショット順を保持したまま返す。 これは、代わりに古典的な結果に対する分布の推定である準確率分布を出力する V1 サンプラーとは対照的である。 さらに、 V2 サンプラーの結果オブジェクトは、入力回路の古典的なレジスタ名でデータを整理するため、ダイナミック回路との自然な互換性が得られる。

    V2 インターフェースにおいて、準確率分布に最も近いものは、以下の例に示す``メソッド get_counts() です。 ただし、実用規模の実験(100クビット以上)においては、同じビット列が2回測定される可能性は低いため、辞書形式でカウントをグループ化するような手法は、通常、効率的なデータ処理戦略とはならないことを強調しておきます。

    circuit = QuantumCircuit(QuantumRegister(2, "qreg"), ClassicalRegister(2, "alpha"))
    circuit.h(0)
    circuit.cx(0, 1)
    circuit.measure([0, 1], [0, 1])
    
    # V1 sampler usage
    result = sampler_v1.run([circuit]).result()
    quasi_dist = result.quasi_dists[0]
    
    # V2 sampler usage
    result = sampler_v2.run([circuit]).result()
    # these are the bit values from the alpha register, over all shots
    bitvals = result[0].data.alpha
    # we can use it to generate a Counts mapping, which is similar to a quasi prob distribution
    counts = bitvals.get_counts()
    # which can in turn be converted to the V1 type through normalization
    quasi_dist = QuasiDistribution({outcome: freq / shots for outcome, freq in counts.items()})
  3. V2 のプリミティブは、すべての量子システムに固有の確率的性質に起因する「サンプリングオーバーヘッド」という概念を、単なるオプションの範囲からAPIそのものの中に組み込みました。 shotsサンプラーにとって、これは、引 shots 数がシグネチャ run() の一部となったことを意味します。さらに、各パブは `` に対して独自の値を指定することができ、その値はメソッドに与えられた値よりも優先されます。 この推定関数には、プリミティブ実装が期待値の推定値として目指すべき誤差範囲を指定する、同 precision 様の引数が用意されています。

    この概念は V1 プリミティブのAPIには存在しないが、 V1 プリミティブのすべての実装には、オプションのどこかに関連する設定がある。

    # Sample two circuits at 128 shots each.
    sampler_v2.run([circuit1, 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_v2.run([(circuit1, None, 123), (circuit2, None, 456)])
    
    # Estimate expectation values for two pubs, both with 0.05 precision.
    estimator_v2.run([(circuit1, obs_array1), (circuit2, obs_array_2)], precision=0.05)

プリミティブ API

パラメータ V2

ParameterLikeユニオン型を表す
BindingsArray( [データ、形状] ). に対するパラメータ qiskit.QuantumCircuitバインディングの値セットを保存します。
BindingsArrayLike別名 `Mapping[ParameterLike

見積もりツール V2

BaseEstimatorV2()EstimatorV2 実装のための基本クラス。
StatevectorEstimator(*[, default_precision,...] )完全な状態ベクトルシミュレーションを備えた、の BaseEstimatorV2 シンプルな実装。
BackendEstimatorV2(*, バックエンド[, オプション] )提供された量子回路と観測値の組み合わせに対する期待値を評価する。
EstimatorPub(回路、観測量[、……] )任意の推定子プリミティブ用のプリミティブ統一ブロック。
ObservablesArray(観測量[, 量子ビット数,...] )ある Estimator 原始関数に対するエルミート観測量のND配列。
ObservableLikeユニオン型を表す
EstimatorPubLike別名 EstimatorPub
ObservablesArrayLike別名 `ObservableLike

サンプラー V2

BaseSamplerV2()SamplerV2 実装のための基本クラス。
StatevectorSampler(*[, default_shots, seed] )完全な状態ベクトルシミュレーションを用いた、の BaseSamplerV2 簡単な実装。
BackendSamplerV2(*, バックエンド[, オプション] )提供された量子回路のビット列を評価する
SamplerPub(回路[, パラメータ値,...] )サンプラー用のPub(Primitive Unified Bloc)。
SamplerPubLike別名 SamplerPub

結果 V2

BitArray(配列, ビット数)ビット値の配列を格納する。
DataBin(*[, shape] )PubResult.にある1軒のパブからの主なデータ報告は、以下の通りです。
PrimitiveResult(pub_results[, metadata] )複数のパブの結果とグローバルなメタデータを格納するコンテナ。
PubResult(データ[、メタデータ] )単一のパブ(プリミティブ統一ブロック)に対する結果オブジェクト。
SamplerPubResult(データ[、メタデータ] )サンプラー・パブの結果
BasePrimitiveJob(job_id, **kwargs)プリミティブジョブの抽象ベースクラス。
PrimitiveJob(function, *args, **kwargs)Qiskitのプリミティブの参照実装からジョブへのハンドル。

見積もりツール V1

BaseEstimatorV1(*[, オプション] )EstimatorV1 実装のための基本クラス。
EstimatorResult(値、メタデータ)エスティメーターの結果 V1.

サンプラー V1

BaseSamplerV1(*[, オプション] )サンプラー V1 基本クラス
SamplerResult(quasi_dists, metadata)サンプラーの結果 V1.
このページは役に立ちましたか?
バグや誤字の報告、またはコンテンツの要求はGitHubで行ってください。