メインコンテンツへスキップ
このプロジェクトはベータ版です。バグを見つけましたか?GitHub Issueを開く。質問やアイデアがありますか?Discussionsで質問する — フィードバックをお待ちしています!
このページの翻訳品質はいかがですか?

Qiskit Aer primitiveによる完全シミュレーションとノイズありシミュレーション

Package versions

このページのコードは、以下の要件を使用して開発されました。これらのバージョン以降を使用することをお勧めします。

qiskit[all]~=2.5.2
qiskit-aer~=0.17

Qiskit SDK プリミティブによる完全シミュレーションでは、Qiskitに含まれるリファレンス・プリミティブを使用して量子回路の完全シミュレーションを実行する方法を説明しています。現在存在する量子プロセッサーにはエラー、つまりノイズがあるため、完全シミュレーションの結果は、実機で回路を実行したときに期待される結果を必ずしも反映するとは限りません。Qiskitのリファレンス・プリミティブはノイズのモデリングをサポートしていませんが、Qiskit Aerにはノイズのモデリングをサポートするプリミティブの実装が含まれています。Qiskit Aerは高性能な量子回路シミュレーターであり、より優れたパフォーマンスと多くの機能を求める場合にリファレンス・プリミティブの代わりに使用できます。これはQiskit Ecosystemの一部です。この記事では、完全シミュレーションとノイズありシミュレーションのためのQiskit Aerプリミティブの使用方法を説明します。

Notes
  • qiskit-aer v0.14以降が必要です。
  • Qiskit Aerプリミティブはプリミティブ・インターフェースを実装していますが、IBM Quantumプリミティブと同じオプションは提供していません。例えば、レジリエンス・レベルはQiskit Aerプリミティブでは利用できません。
  • Aerがサポートするシミュレーション方式のオプションの詳細については、AerSimulatorのドキュメントを参照してください。

正確なシミュレーションとノイズのあるシミュレーションを確認するために、8量子ビットの例の回路を作成します。

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"qiskit": "qiskit", "qiskit_aer": "qiskit-aer"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
from qiskit.circuit.library import efficient_su2

n_qubits = 8
circuit = efficient_su2(n_qubits)
circuit.draw("mpl")

Output of the previous code cell

この回路には、RyR_yおよびRzR_zゲートの回転角度を表すパラメーターが含まれています。この回路をシミュレートする際には、これらのパラメーターに明示的な値を指定する必要があります。次のセルでは、これらのパラメーターにいくつかの値を指定し、Qiskit AerのEstimatorプリミティブを使用して、オブザーバブルZZ⋯ZZZ \cdots Zの正確な期待値を計算します。

from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_aer import AerSimulator
from qiskit_aer.primitives import EstimatorV2 as Estimator

observable = SparsePauliOp("Z" * n_qubits)
params = [0.1] * circuit.num_parameters

exact_estimator = Estimator()
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(circuit)
pub = (isa_circuit, observable, params)
job = exact_estimator.run([pub])
result = job.result()
pub_result = result[0]
exact_value = float(pub_result.data.evs)
exact_value
0.8870140234256602

次に、すべてのCXゲートに2%の脱分極エラーを含むノイズモデルを初期化します。実際には、2量子ビットゲート(ここではCXゲート)から生じるエラーが、回路を実行する際の主要なエラー源です。Qiskit Aerでのノイズモデルの構築の概要については、ノイズモデルの構築を参照してください。

次のセルでは、このノイズモデルを組み込んだEstimatorを構築し、それを使用してオブザーバブルの期待値を計算します。

from qiskit_aer.noise import NoiseModel, depolarizing_error

noise_model = NoiseModel()
cx_depolarizing_prob = 0.02
noise_model.add_all_qubit_quantum_error(
depolarizing_error(cx_depolarizing_prob, 2), ["cx"]
)

noisy_estimator = Estimator(
options=dict(backend_options=dict(noise_model=noise_model))
)
job = noisy_estimator.run([pub])
result = job.result()
pub_result = result[0]
noisy_value = float(pub_result.data.evs)
noisy_value
0.7247404214143529

ご覧の通り、ノイズが存在する場合の期待値は正しい値からかなり離れています。実際には、ノイズの影響に対抗するためにさまざまなエラー緩和技術を使用できますが、これらの技術についての議論は本記事の範囲外です。

ノイズが最終結果にどのように影響するかを大まかに把握するために、各CXゲートに2%の脱分極エラーを追加するノイズモデルを考えます。確率ppの脱分極エラーは、密度行列ρ\rhoに対して以下のような作用を持つ量子チャネルEEとして定義されます。

E(ρ)=(1−p)ρ+pI2nE(\rho) = (1 - p) \rho + p\frac{I}{2^n}

ここでnnは量子ビットの数で、この場合は2です。つまり、確率ppで状態は完全混合状態に置き換えられ、確率1−p1 - pで状態は保持されます。脱分極チャネルをmm回適用した後、状態が保持される確率は(1−p)m(1 - p)^mになります。したがって、シミュレーションの最後で正しい状態が保持される確率は、回路内のCXゲートの数に応じて指数関数的に減少すると予想されます。

回路内のCXゲートの数を数えて、(1−p)m(1 - p)^mを計算しましょう。count_opsを呼び出して、ゲート名を個数にマップする辞書を取得し、CXゲートのエントリを取得します。

cx_count = circuit.count_ops()["cx"]
(1 - cx_depolarizing_prob) ** cx_count
0.6542558123199923

この値、65%は、最終状態が正しい確率のおおよその推定値です。シミュレーションの初期状態を考慮していないため、これは控えめな推定値です。

次のコード・セルでは、Qiskit AerのSamplerプリミティブを使用してノイズのある回路からサンプリングする方法を示します。Samplerプリミティブで回路を実行する前に、回路に測定を追加する必要があります。

from qiskit_aer.primitives import SamplerV2 as Sampler

measured_circuit = circuit.copy()
measured_circuit.measure_all()

noisy_sampler = Sampler(
options=dict(backend_options=dict(noise_model=noise_model))
)
# The circuit needs to be transpiled to the AerSimulator target
pass_manager = generate_preset_pass_manager(3, AerSimulator())
isa_circuit = pass_manager.run(measured_circuit)
pub = (isa_circuit, params, 100)
job = noisy_sampler.run([pub])
result = job.result()
pub_result = result[0]
pub_result.data.meas.get_counts()
{'00000000': 69,
'00100000': 2,
'00000110': 1,
'11000000': 2,
'00010100': 1,
'01100000': 2,
'01010000': 3,
'00101000': 1,
'10100000': 2,
'01100101': 1,
'00001010': 1,
'10000000': 2,
'00000010': 3,
'01000000': 4,
'11100000': 1,
'10000101': 1,
'00110000': 1,
'00001100': 1,
'00011000': 2}

次のステップ​

おすすめ