サーバーサイドのサンプラーおよびエスティメータからクライアントサイドのものへ移行する
このガイドでは、IBM Quantum®
Sampler
および のサーバーサイド
実装から、
qiskit-ibm-runtime
の新しいクライアントサイド
実装Estimator
へ移行する方法について説明します。 インターフェースやオプションは概ね変更されていないため、ほとんどのコードは
そのまま動作しますが、理解しておくべき動作上の違いがいくつかあります。
背景
Sampler と Estimator は、Qiskit で定義されているプリミティブインターフェースです。 IBM Quantum
Compute
サービス(旧称:Qiskit Runtime
)は、これまでそのランタイム環境内でこれらのプリミティブの実装を提供
してきました。 や sampler.run()
estimator.run()を呼び出すと、リクエストがサービスに送信され、
エラーの抑制や緩和を含むすべての処理がサーバー側で行われます。
このブラックボックス的な仕組みは便利で、実装の 詳細について気にする必要がありません。 しかし、その一方で、処理中に何が起きているのかがわからないため、 プリミティブのデバッグやカスタマイズ、あるいはそこから学ぶことも難しくなってしまいます。
新たに導入されたディレクテッド実行モデルは、これとは逆のアプローチを採用し、 ホワイトボックス型の体験を提供します。 すべての設計意図はクライアント側で把握され、 単一のサーバーサイドプリミティブである Executor が、それらの入力を指示どおりに正確に処理します。 つまり、ユーザーに代わって暗黙的な判断を行うことはありません。
v0.50.0 以降、Sampler と Estimator qiskit-ibm-runtime は、
Executor を基盤としてクライアント側で再実装されています。 これらは以前と同じ利便性と
抽象化を提供しており、必要に応じて
実装の詳細を確認できるようになりました。 インターフェースやオプションは概ね同じままであるため、移行は
スムーズに行われるはずです。
注: IBM Quantum は、SamplerおよびEstimatorインターフェースのバージョン2(BaseSamplerV2 および BaseEstimatorV2)のみをサポートしています。 したがって、本ガイドでは、これらを単に「サンプラー」および「推定器」と呼ぶことにする。
インポートを更新する
現在では、新しい実装を、それ専用のモジュールから明示的にインポートする必要があります:
from qiskit_ibm_runtime.executor_sampler import Sampler
from qiskit_ibm_runtime.executor_estimator import Estimator近い将来、トップレベルのインポートは新しいクライアントサイドの 実装に解決されるようになり、コードの変更は一切必要なくなります:
# Coming soon — the following code will import the new client-side implementations.
from qiskit_ibm_runtime import Sampler, Estimator同様に、型付きオプションオブジェクトを作成する場合は、代わりにそれらをインポートするか
qiskit_ibm_runtime.options_models 、あるいは単に単純なネストされた辞書を渡す必要があります:
from qiskit_ibm_runtime.options_models import SamplerOptions, EstimatorOptionsこれまでと何が同じか
- と
modeを用いた単純な構成options。 - 署名
run()および PUB 形式。 - オプションツリー(
options.twirling、options.resilience、、options.default_shots、 など)。 - . によって返される結果のデータ構造は
job.result()、
新しいSamplerにおける互換性のない変更点
変更 | 移住措置 |
|---|---|
基礎となるプリミティブは、現在「Executor」となっています。 IBM Quantum Platform のユーザーインターフェースと の両方で、 の executor 代わりに job.primitive_id が表示されます sampler。 | . を参照しているコードをすべて更新してください job.primitive_id。 |
この新しい実装では、サンプラーの入力値がエグゼキュータの入力値にマッピングされるため、エグゼキュータの入力値を job.inputs 返します。 | . を参照しているコードをすべて更新してください job.inputs。 「ジョブの入力」 を参照してください。 |
前処理や後処理の多くがクライアント側で行われるようになったため、 sampler.run() および の処理に以前より時間がかかる job.result() 場合があります。 | クライアント側の処理の進行状況を追跡するために、INFO ロギングを有効にします。 「INFO ロギングを有効にする」 を参照してください。 |
回路のメタデータが結果のメタデータにコピーされます。 結果メタデータで使用できるデータ型は str、 float, int,, bool, およびそれらの型のリストや辞書に限定されるようになりました。 | 他のデータ型が必要な場合は、まずそれらを文字列としてエンコードしてください(例: base64 )。 |
オプションクラス(options_models.SamplerOptions など)は、dataclass ではなく Pydantic モデルになったため、. を使用して Python の辞書に変換することはできなくなりました asdict()。 | 代わりに options.model_dump() を使用してください。 |
以前は接尾 V2 辞(ExecutionOptionsV2 など)が付いていたオプションクラスは、 V1 のプリミティブがサポートされなくなったため、現在ではその接尾辞が付かなくなりました。 | これらのオプションクラスの接尾 V2 辞を削除してください。を ExecutionOptionsV2 に ExecutionOptions、を ResilienceOptionsV2 に ResilienceOptions、を SamplerExecutionOptionsV2 に置き換えてください SamplerExecutionOptions。 |
が有効になって twirling おり、かつ shots (PUB内または run())で、、 shots_per_randomization、および がすべて指定されている num_randomizations 場合、 は より優先 num_randomizations * shots_per_randomization されます shots。 | 値 shots を使用したい shots_per_randomization 場合は、と num_randomizations を省略してください。 |
一部の入力検証がサーバー側に移行され、以前は を発生させていた RuntimeError ものが、現在は を発生させるようになりました IBMInputValueError。 | コードでキャッチしている例外の種類を更新してください。 |
| 1つのジョブ内で異なるショット値を使用することは、もはやサポートされていません。 | ショット値ごとに個別のジョブを送信してください。 考慮すべき点については、「 ジョブ分割」 を参照してください。 |
新しいEstimatorにおける互換性のない変更点
変更 | 移住措置 |
|---|---|
基礎となるプリミティブは、現在「Executor」となっています。 IBM Quantum Platform のユーザーインターフェースと の両方で、 の executor 代わりに job.primitive_id が表示されます estimator。 | . を参照しているコードをすべて更新してください job.primitive_id。 |
この新しい実装では、Estimatorの入力とExecutorの入力を対応付けしているため、Executorの入力を job.inputs 返します。 | . を参照しているコードをすべて更新してください job.inputs。 「ジョブの入力」 を参照してください。 |
前処理や後処理の多くがクライアント側で行われるようになったため、 estimator.run() および の処理に以前より時間がかかる job.result() 場合があります。 | クライアント側の処理の進行状況を追跡するために、INFO ロギングを有効にします。 「INFO ロギングを有効にする」 を参照してください。 |
回路のメタデータが結果のメタデータにコピーされます。 結果メタデータで使用できるデータ型は str、 float, int,, bool, およびそれらの型のリストや辞書に限定されるようになりました。 | 他のデータ型が必要な場合は、まずそれらを文字列としてエンコードしてください(例: base64 )。 |
オプションクラス(options_models.EstimatorOptions など)は、dataclass ではなく Pydantic モデルになったため、. を使用して Python の辞書に変換することはできなくなりました asdict()。 | 代わりに options.model_dump() を使用してください。 |
V1 のプリミティブがサポートされなくなったため、以前「ExecutionOptionsV2 」などの接尾 V2 辞が付いていたオプションクラスは、もはやその接尾辞が付かなくなりました。 | これらのオプションクラスの接尾 V2 辞を削除してください。を ExecutionOptionsV2 に、 ExecutionOptions を ResilienceOptionsV2 に置き換えてください ResilienceOptions。 |
| すべての入力オプションが、選択されたサブセットではなく、結果のメタデータとして返されます。 | なし — これは参考情報です。 |
一部の入力検証がサーバー側に移行され、以前は を発生させていた RuntimeError ものが、現在は を発生させるようになりました IBMInputValueError。 | コードでキャッチしている例外の種類を更新してください。 |
| PEAおよびPECにおける暗黙的なノイズ学習は廃止されました。 TREX向けの測定ノイズ学習は引き続きサポートされています。 | ノイズモデルを個別に学習し、それらをEstimatorに渡します。 「PEAおよびPECに対する明示的なノイズ学習の実行」 を参照してください。 |
の入力型は ResilienceOptions.layer_noise_model 異なり、の NoiseLearnerV3 結果から構築することができます。 | PEA および PEC における明示的なノイズ学習の実施方法については、「明示的なノイズ学習の実施」を参照し、ノイズモデルを学習して Estimator に渡す方法を確認 NoiseLearnerV3 してください。 |
MeasureNoiseLearningOptions.shots_per_randomization はサポートされなくなりました。 | 測定ノイズ学習回路を含め、ジョブ内のすべての回路に対して単一のショット値が使用されます。 どうしても別のショット値を使用する必要がある場合は、Estimatorの外部 qiskit-mitigation でTREXを適用してください。 |
| 1つのジョブ内で混合精度の値を指定することは、もはやサポートされていません。 | 希望する精度ごとに、個別のジョブを送信してください。 考慮すべき点については、「 ジョブ分割」 を参照してください。 |
このオプション seed_estimator は、もはやサポートされていません。 | すべての割り当て options.seed_estimator を削除してください(割り当てを設定すると、が発生します ValidationError)。 クライアント側で同等の機能はないため、このシードを通じて結果を再現することはできなくなりました。 |
INFO ロギングを有効にする
現在ではクライアント側で行われる処理が増えているため、その
処理の進捗状況を確認できると便利です。 logger qiskit_ibm_runtime に対して INFO レベルのロギングを有効にします:
import logging
logger = logging.getLogger("qiskit_ibm_runtime")
logger.setLevel(logging.INFO)PEAおよびPECに対して明示的なノイズ学習を実行する
新しいEstimatorでは、PEAまたはPECのエラー低減手法が
選択されている場合、 暗黙的なノイズ学習は行われなくなりました。 ノイズモデルを明示的に学習し、それを
引き渡す必要があります。 新しい を使用して、回路が
レイヤーごとにどのように分類されるかを制御NoiseLearnerV3します。 入力として、ボックス化された回路の指示リスト(例えば、
固有のレイヤーなど)を受け取ります。
PEAおよびPECでは、現在この明示的なパターンが必須となっています。 ノイズ学習のステップを飛ばさないでください。 そうしないと、コードが正常に動作しなくなります。 TREXの測定ノイズ学習には影響がなく、これまで通り動作し続けます。
同様に、コードで を使用し、 NoiseLearner その結果として得られたノイズモデルをサーバーサイドのEstimatorに渡す場合は、 を行う必要があります 移行する NoiseLearnerV3。 新しいEstimatorとは互換性がない旧バージョンは絶対に使用しないでください NoiseLearner。
サーバーサイドのEstimator(LayerNoiseLearningOptions)のノイズ学習オプションはすべて、を除いて、 NoiseLearnerV3 オプション(NoiseLearnerV3Options)に直接対応しています max_layers_to_learn。 学習対象となる層の数は、むしろ に渡される層の数に基づいています NoiseLearnerV3。
例:
サーバーサイド推定器(PEC有効時):
from qiskit_ibm_runtime import Estimator
pubs = [...] # Your PUBs
estimator = Estimator(mode, options)
estimator.options.resilience.pec_mitigation = True # or zne_mitigation + pea amplifier
estimator.options.resilience.layer_noise_learning.num_randomizations = 64
job = estimator.run(pubs)クライアントサイドの推定器(PEC有効時):
from qiskit_ibm_runtime.executor_estimator import Estimator
from qiskit_ibm_runtime import NoiseLearnerV3
pubs = [...] # Your PUBs
estimator = Estimator(mode, options)
estimator.options.resilience.pec_mitigation = True # or zne_mitigation + pea amplifier
# Identify the unique layers to learn.
layers = estimator.find_unique_layers(pubs)
# Learn the noise model for those layers (runs as a separate job).
learner = NoiseLearnerV3(mode)
learner.options.num_randomizations = 64 # Same as layer_noise_learning.num_randomizations
learner_job = learner.run(layers)
learner_result = learner_job.result()
# Convert results to Pauli-Lindblad noise maps.
pauli_lindblad_maps = learner_result.to_pauli_lindblad_maps()
# Assign the learned noise maps so PEA/PEC uses them.
estimator.options.resilience.layer_noise_model = zip(layers, pauli_lindblad_maps)
# Now execute the target PUBs.
job = estimator.run(pubs)から へ NoiseLearner 移行する NoiseLearnerV3
NoiseLearner .のサーバーサイド実装でのみ動作します Estimator。 したがって、コード内で を使用してノイズモデルを学習 NoiseLearner し、それを に渡している場合は Estimator、 を使用するようにコードを更新する必要があります NoiseLearnerV3。
詳細については、ガイド から へ NoiseLearner 移行する NoiseLearnerV3 をご覧ください。
業務の分割
1つのジョブ内のショット値や精度値が混在している場合、そのジョブを複数のジョブに分割する必要が生じたときは、 以下の点に留意してください:
-
PUBをターゲット値ごとにグループ化します。つまり、値ごとに1つのジョブを割り当てるのではなく、異なる値ごとに1つのジョブを割り当てます PUB。 分割は再編成にあたるため、提出するPUBの総数は変わりません。 例えば、が与えられた場合
[[email protected], [email protected], [email protected]]、2つのジョブを提出してください: を[A, C]でprecision=0.01、[B]を でprecision=0.05。 とAを別々のジョブCとして送信すると、各ジョブには一定のオーバーヘッドがかかるため、効率が悪くなります。 -
一度学習すれば、すべての分割ジョブでノイズモデルを利用できます。 すべてのレイヤーの和集合に対して、 単一の
NoiseLearnerV3ジョブを実行するほうが効率的です。 ノイズ学習ジョブの結果には、オブジェクトNoiseLearnerV3Resultのリストが含まれており、 入力命令ごとに1つずつあり、入力リストと同じ順序になっています。 このノイズ学習ジョブの出力は、 すべてのスプリット(推定器)ジョブで使用できます。また、スプリットジョブのPUBに含まれていないレイヤーのノイズ モデルは無視されます。 -
まず
Batch、分割されたすべてのジョブを送信し、その後、それらの結果を集約します。 この実行Batchモードは、複数のジョブが存在する場合に、効率的な並列実行を実現します。 しかし、 はブロック型であるjob.result()ため、サブミッションループ内でこれを呼び出すと、ジョブがシリアル化され、 を使用するメリットが失われてしまいますBatch。 必ず「すべて送信してから一括取得」というパターン(以下に示す通り)を使用してください。
次の例では、 と pub1 には が必要 pub2 ですが precision=0.5、 には が必要です pub3``precision=0.1 :
group1_pubs = [pub1, pub2]
group2_pubs = [pub3]
with Batch(backend=backend) as batch:
estimator = Estimator(mode=batch)
estimator.options.resilience.pec_mitigation = True
# Learn once, over the union of every job's layers.
all_layers = estimator.find_unique_layers(group1_pubs + group2_pubs)
learner_job = NoiseLearnerV3(mode=batch).run(all_layers)
learner_result = learner_job.result()
pauli_lindblad_maps = learner_result.to_pauli_lindblad_maps()
# Assign the learned noise maps. Any layers not found in the input PUBs are ignored.
estimator.options.resilience.layer_noise_model = zip(all_layers, pauli_lindblad_maps)
# Submit every split job with different precision values.
jobs = []
jobs.append(estimator.run(group1_pubs, precision=0.5))
jobs.append(estimator.run(group2_pubs, precision=0.1))
# Block once, at the end — the jobs run in parallel.
results = [job.result() for job in jobs]ジョブの入力構造
この新しい実装では、Sampler または Estimator の入力を Executor の入力にマッピングするため、Executor の入力を含む辞書を job.inputs 返します。 この辞書には、以下のキーが含まれています:
options: 入力ExecutorOption.quantum_program: 入力QuantumProgramschema_version: 使用されるサーバー側のスキーマのバージョン。
これまで、ジョブに指定されたオプションを取得 job.inputs['options'] するためにコードを使用していた場合は、今後は job.result().metadata['options'] 代わりに を使用できます。
偽のバックエンドを使ってローカルでテストする
ハードウェアに送信する前に、移行したコードをバック Fake*
エンドに対して検証することで、構文エラーを早期に検出することができます。 ローカルテストモードについては、以下の点に注意してください:
- ハードウェアでの結果を再現するものではありません。 ローカルノイズシミュレーションでは、実際のデバイスのノイズを完全に 再現できないため、出力結果が異なる場合があります。 実行することで、 オプションのパスと値の型が正しいことが確認されます。
NoiseLearnerV3ローカルテストモードがありません。この関数は実数Backend、Sessionまたはのみを受け付けるmodeためBatch、偽の バックエンドに対してノイズ学習ステップを実行することはできません。 そのコードの一部については、代わりにそちらNoiseLearnerV3APIリファレンス で検証してください。 コンストラクタ、 入run(instructions)力の形状、およびヘルパー(ユニークレイヤー・ヘルパーなど)が、 ドキュメントに記載されている通りに使用されていることを確認してください。
効率的なローカルシミュレーションのために回路をクリフォード化します
偽のバックエンドは、状態ベクトル(ノイズあり)シミュレータを使用しており、その計算コストは
量子ビット数と深さに比例して指数関数的に増加する。 したがって、現実的な負荷を想定した回路では、ハングアップしたり、メモリを使い果たしたりする可能性があります。 ローカルでのテストでは、
オプションの経路を検証するだけでよく(物理的な結果を再現する必要はないため)、
まず次の式を用いて回路をクリフォード回路に還元します。
これにより
ConvertISAToClifford、各 RZ``RZZ//RX 角度が π/2 の倍数に丸められます。 クリフォード回路は、
規模にかかわらず効率的にシミュレーション(スタビライザーシミュレーション)を行うことができます。
from qiskit.transpiler import PassManager
from qiskit_ibm_runtime.transpiler.passes import ConvertISAToClifford
clifford = PassManager([ConvertISAToClifford()]).run(isa_circuit)
# run `clifford` (not the original) through the fake-backend primitiveConvertISAToClifford 入力として ISA回路を必要とする (
generate_preset_pass_manager(...).run(...) バックエンド向けの出力)。 ローカルな PUB を構築する際には、
以下の影響を考慮する必要があります:
- この属性
.layoutは削除されます。 クリフォード化された回路は量子ビットの数は同じままですが、 は であるclifford.layoutためNone、observable.apply_layout(clifford.layout)失敗します。 代わりに、 クリフォード化前のISA回路から観測可能量を抽出します:isa_obs = observable.apply_layout(isa_circuit.layout)、その後、を実行します(clifford, isa_obs)。 - パラメータは外部にバインドされています。 回転角を丸めると、パラメトリックなISA回路が
具体的なクリフォード回路に変わり、したがって は となる
clifford.num_parameters``0。 PUB が依然として パラメータ値の配列を保持している場合、型変換に失敗します。 ローカル実行の場合は、 PUB からパラメータ 配列を削除してください。ハードウェア実行では、元のパラメトリック回路とその値が保持されます。