Japanese
言語
English
Japanese
Spanish

Qiskit Runtimeのノイズのあるシミュレーター

このノートブックは、 ibmq_qasm_simulator をセットアップし、Qiskit Runtime でIBM Quantumハードウェア・デバイス用の基本的なノイズモデルをマッピングする方法を示します。 実際のデバイスで発生するエラーの影響を調べるために、このノイズモデルを使用して、 SamplerEstimator 上で QuantumCircuits のノイズ・シミュレーションを行います。

ローカル開発環境のセットアップ

このチュートリアルでは、Qiskit Runtime サービス・インスタンスが必要です。まだ実行していない場合は、これらの手順 に従ってセットアップしてください。

# load necessary Runtime libraries
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler, Estimator, Session, Options

service = QiskitRuntimeService(channel="ibm_quantum")

環境の準備

デモンストレーションをするために、サンプル・ルーチンを実行していきましょう。 primitiveを使用する主な利点の 1 つは、パラメーター化された回路で、複数のパラメーターの結合を単純化することです。 これを確認するために、制御 P ゲート を持つ回路の例を以下のコードに示します。 ここでは、P-gate を回転パラメーター theta でパラメーター化します。 Qiskitを使用して回路作成しパラメーターを結合する方法を学習するには、 Qiskit ドキュメンテーションの 回路の基本 および 回路の応用 を参照してください。

from qiskit.circuit import Parameter
from qiskit import QuantumCircuit

theta = Parameter('theta')

qc = QuantumCircuit(2,1)
qc.x(1)
qc.h(0)
qc.cp(theta,0,1)
qc.h(0)
qc.measure(0,0)

qc.draw('mpl')
../_images/noisy-sim-circuit.png

前のセルで示した回路は、測定する量子ビット0にキックバックされる固有値でパラメーター化されます。 キックバックの量はパラメーター thetaによって決定されます。 以下のセルでは、上記の回路のパラメーターをリストとして定義します。 ここでのパラメーターは、 \(0\) から \(2\pi\) までで、50個の均等な間隔の点に分けられます。

import numpy as np

phases = np.linspace(0, 2*np.pi, 50)

# phases need to be expressed as a list of lists in order to work
individual_phases = [[phase] for phase in phases]

理想的なシミュレーターでの実行

使用するバックエンドとオプションの設定

最初に、Sampler と Estimator の両方で noise_modeloptimization_level または reverence_level がない理想的なケースを使用して実行することを示します。 以下のコードではオプションの設定に進みます。

backend = "ibmq_qasm_simulator" # use the simulator
options = Options()
options.simulator.seed_simulator = 42
options.execution.shots = 1000
options.optimization_level = 0 # no optimization
options.resilience_level = 0 # no error mitigation

Samplerでの回路の実行

ここで、 Sampler primitive を使用して回路をサンプリングし、結果の確率分布を取得します。 Sampler primitive の使用方法および Qiskit Runtime Sessionの使用開始方法については、次のチュートリアルで確認することができます: `Sampler primitive 入門<https://qiskit.org/documentation/partners/qiskit_ibm_runtime/tutorials/how-to-getting-started-with-sampler.html>`__

with Session(service=service, backend=backend):
    sampler = Sampler(options=options)
    job = sampler.run(
        circuits=[qc]*len(phases),
        parameter_values=individual_phases
    )
    result = job.result()
import matplotlib.pyplot as plt

# the probablity of being in the 1 state for each of these values
prob_values = [dist.get(1, 0) for dist in result.quasi_dists]

plt.plot(phases, prob_values, 'o', label='Simulator')
plt.plot(phases, np.sin(phases/2,)**2, label='Theory')
plt.xlabel('Phase')
plt.ylabel('Probability')
plt.legend()
<matplotlib.legend.Legend at 0x7f7fd233b6d0>
../_images/noisy-sim-sampler-ideal.png

Estimatorでの回路の実行

Estimator のためのセッションを開始する方法を学ぶには、次のチュートリアルの確認してください: Estimator primitive 入門

このEstimatorは、量子演算子の期待値を返す前に、単一量子ビット回転を結合してハミルトニアンを得ます。 したがって、回路は測定を必要としません。現在の回路 qc には測定がありますので、remove_final_measurements でこれを削除します。

qc_no_meas = qc.remove_final_measurements(inplace=False)
qc_no_meas.draw('mpl')
../_images/noisy-sim-estimator-circuit.png
from qiskit.quantum_info import SparsePauliOp

ZZ = SparsePauliOp.from_list([("ZZ", 1)])
print(f"  > Observable: {ZZ.paulis}")
> Observable: ['ZZ']

この観測量を使用すると、期待値は以下の式で計算されます。

\[\langle ZZ\rangle =\langle \psi | ZZ | \psi\rangle=\langle \psi|(|0\rangle\langle 0| -|1\rangle\langle 1|)\otimes(|0\rangle\langle 0| - |1\rangle\langle 1|) |\psi\rangle =|\langle 00|\psi\rangle|^2 - |\langle 01 | \psi\rangle|^2 - |\langle 10 | \psi\rangle|^2 + |\langle 11|\psi\rangle|^2\]

次のセルは、ここで示したものを実装します。

with Session(service=service, backend=backend):
    estimator = Estimator(options=options)
    job = estimator.run(
        circuits=[qc_no_meas]*len(phases),
        parameter_values=individual_phases,
        observables=[ZZ]*len(phases)
    )
    result = job.result()
exp_values = result.values

plt.plot(phases, exp_values, 'o', label='Simulator')
plt.plot(phases, 2*np.sin(phases/2)**2-1, label='Theory')
plt.xlabel('Phase')
plt.ylabel('Expectation')
plt.legend()
<matplotlib.legend.Legend at 0x7f7fd0ed8820>
../_images/noisy-sim-estimator-ideal.png

ノイズのあるシミュレーションの実行

次に、理想的なシミュレーションではなく、ノイズのあるシミュレーションを実行するためのシミュレーターを設定します。 Options パラメーターに指定することで、Runtime のシミュレーターにカスタムの noise_model を渡すことができます。 ここでは実際のバックエンドを模倣し、FakeBackend クラスから noise_model をマップします。 ノイズモデルは FakeBackend から抽出し、オプションの simulator パラメーターとして渡すことができます。 fake_provider についてもっと知りたい場合は、Qiskit ドキュメンテーションの Fake Provider を参照してください。

本物のバックエンドを模倣しようとしているので、より現実的なノイズ・シミュレーションをサポートするための、バックエンドのトポロジーを表す coupling_map と、バックエンドがサポートする ``basis_gates``を渡すこともできます。

from qiskit.providers.fake_provider import FakeManila
from qiskit_aer.noise import NoiseModel

# Make a noise model
fake_backend = FakeManila()
noise_model = NoiseModel.from_backend(fake_backend)

# Set options to include the noise model
options = Options()
options.simulator = {
    "noise_model": noise_model,
    "basis_gates": fake_backend.configuration().basis_gates,
    "coupling_map": fake_backend.configuration().coupling_map,
    "seed_simulator": 42
}

# Set number of shots, optimization_level and resilience_level
options.execution.shots = 1000
options.optimization_level = 0
options.resilience_level = 0

ibmq_qasm_simulator は、Qiskit Runtime Service が提供する resilience_levels を有効にします。 シミュレーターでこれらのレベルを使用することで、以前のようなノイズのあるシミュレーションが最もよくデモンストレーションされます。

比較を見るには、Options の2つのセットを定義します。 ibmq_qasm_simulator シミュレーターは、Qiskit Runtimeによって提供されるresilienceレベルを有効化します。シミュレーターでのこれらのレベルを使うには我々が構築したノイズのあるシミュレーションを使ってデモを行うことが最適です。 ここで、options はエラー緩和なしの通常の実行を表すために resilience level = 0 に設定されます。 そして options with emresilience level = 1 に設定され、エラー緩和が有効になっている実行を表します。

# Set options to include the noise model with error mitigation
options_with_em = Options()
options_with_em.simulator = {
    "noise_model": noise_model,
    "basis_gates": fake_backend.configuration().basis_gates,
    "coupling_map": fake_backend.configuration().coupling_map,
    "seed_simulator": 42
}

# Set number of shots, optimization_level and resilience_level
options_with_em.execution.shots = 1000
options_with_em.optimization_level = 0 # no optimization
options_with_em.resilience_level = 1 # M3 for Sampler and T-REx for Estimator

resilience_level を 1 に設定すると、SamplerでM3が有効になります。利用可能なすべてのresilienceレベルの設定は、 ここ で確認できます。

with Session(service=service, backend=backend):
    # include the noise model without M3
    sampler = Sampler(options=options)
    job = sampler.run(
        circuits=[qc]*len(phases),
        parameter_values=individual_phases
    )
    result = job.result()
    prob_values = [1-dist[0] for dist in result.quasi_dists]

    # include the noise model with M3
    sampler = Sampler(options=options_with_em)
    job = sampler.run(
        circuits=[qc]*len(phases),
        parameter_values=individual_phases
    )
    result = job.result()
    prob_values_with_em = [1-dist[0] for dist in result.quasi_dists]
plt.plot(phases, prob_values, 'o', label='Noisy')
plt.plot(phases, prob_values_with_em, 'o', label='Mitigated')
plt.plot(phases, np.sin(phases/2,)**2, label='Theory')
plt.xlabel('Phase')
plt.ylabel('Probability')
plt.legend()
<matplotlib.legend.Legend at 0x7f7fb4230700>
../_images/noisy-sim-sampler-noisy.png

T-REx はresilienceレベルが 1 に設定されている場合に、Estimator で起動されます。

with Session(service=service, backend=backend):
    # include the noise model without T-REx
    estimator = Estimator(options=options)
    job = estimator.run(
        circuits=[qc_no_meas]*len(phases),
        parameter_values=individual_phases,
        observables=[ZZ]*len(phases)
    )
    result = job.result()
    exp_values = result.values

    # include the noise model with T-REx
    estimator = Estimator(options=options_with_em)
    job = estimator.run(
        circuits=[qc_no_meas]*len(phases),
        parameter_values=individual_phases,
        observables=[ZZ]*len(phases))
    result = job.result()
    exp_values_with_em = result.values
plt.plot(phases, exp_values, 'o', label='Noisy')
plt.plot(phases, exp_values_with_em, 'o', label='Mitigated')
plt.plot(phases, 2*np.sin(phases/2)**2-1, label='Theory')
plt.xlabel('Phase')
plt.ylabel('Expectation')
plt.legend()
<matplotlib.legend.Legend at 0x7f7f7006ca00>
../_images/noisy-sim-estimator-noisy.png

Resilience レベルは現在ベータ版のため、サンプリングのオーバーヘッドとソリューションの品質は回路によって異なります。 新機能、高度なオプションおよび管理ツールは、順次リリースされます。 またより高いレベルのresilienceを設定し、それらによって提供される追加オプションを探索することもできます。 上記の例で示した M3T-REx に加えて、 Digital-ZNEPEC のような機能の有効化についてもっと知りたい場合は、次のチュートリアルを確認してください: Qiskit Runtimeによるエラーの抑制とエラーの軽減

import qiskit_ibm_runtime
qiskit_ibm_runtime.version.get_version_info()
'0.8.0'
from qiskit.tools.jupyter import *
%qiskit_version_table

Version Information

Qiskit SoftwareVersion
qiskit-terra0.22.2
qiskit-aer0.11.1
qiskit-ibmq-provider0.19.2
qiskit0.39.2
qiskit-nature0.5.0
qiskit-finance0.3.4
qiskit-optimization0.4.0
qiskit-machine-learning0.5.0
System information
Python version3.8.13
Python compilerGCC 10.3.0
Python builddefault, Mar 25 2022 06:04:10
OSLinux
CPUs8
Memory (Gb)31.211326599121094
Wed Nov 30 02:43:41 2022 UTC