注釈

このページは `docs/tutorials/07_leveraging_qiskit_runtime.ipynb`__ から生成されました。

Qiskit Runtimeの活用#

警告

このチュートリアルで説明されている VQEClient は、Qiskit Nature バージョン 0.6 の時点で 非推奨 で、リリースから3ヶ月以内に削除されます。 代わりに、新しいprimitiveベースの VQE を、Qiskit IBM Runtime Estimate primitive とともに使用する必要があります。 移行方法の詳細については、 `こちら<https://qisk.it/algo_migration#vqe>`__ のガイドを参照してください 。

変分量子固有値ソルバー(VQE)のような反復アルゴリズムでは,従来,反復ごとに1つの回路バッチ(1つの「ジョブ」)を送信して量子デバイス上で実行していました。ジョブの送信には、以下のようなオーバーヘッドがあります。

  • リクエストを処理してデータを送信する時間。(APIのオーバーヘッド、通常は約10秒)

  • ジョブのキュータイム、つまり、デバイス上で実行する順番が来るまでの待ち時間。(通常は約2分)

何百ものジョブを繰り返し送信すると、このオーバーヘッドがすぐにアルゴリズムの実行時間を支配してしまいます。Qiskit Runtimeにより、これらの問題に取り組み、(特に)反復アルゴリズムを大幅に高速化することができます。Qiskit Runtimeでは、1つのジョブは回路のバッチだけではなく、アルゴリズム 全体 を含みます。つまり、APIのオーバーヘッドとキューの待ち時間は、反復ごとではなく、 一度 だけ発生するということです。アルゴリズムのパラメーターをアップロードして、プログラムが実行されるクラウドにすべての複雑さを委ねることも、個人のアルゴリズムを直接アップロードすることもできるでしょう。

VQEの場合、既存のコードにQiskit Runtimeを統合することは簡単です。 VQE クラスには VQEClient と呼ばれる(ほぼ)ドロップインの代替品があります。

簡単な化学の例でruntimeをどのように活用できるか見てみましょう。:与えられた結合距離におけるリチウムハイドレート(LiH)分子の基底状態エネルギーを求めます。

問題の指定:LiH分子#

まず、基底状態エネルギーを求める分子を指定します。ここでは、結合距離が2.5ÅのLiHを見てみましょう。

[1]:
from qiskit_nature.units import DistanceUnit
from qiskit_nature.second_q.drivers import PySCFDriver
from qiskit_nature.second_q.mappers import ParityMapper
from qiskit_nature.second_q.properties import ParticleNumber
from qiskit_nature.second_q.transformers import ActiveSpaceTransformer
[2]:
bond_distance = 2.5  # in Angstrom

# specify driver
driver = PySCFDriver(
    atom=f"Li 0 0 0; H 0 0 {bond_distance}",
    basis="sto3g",
    charge=0,
    spin=0,
    unit=DistanceUnit.ANGSTROM,
)
problem = driver.run()

# specify active space transformation
active_space_trafo = ActiveSpaceTransformer(
    num_electrons=problem.num_particles, num_spatial_orbitals=3
)

# transform the electronic structure problem
problem = active_space_trafo.transform(problem)

# construct the parity mapper with 2-qubit reduction
qubit_mapper = ParityMapper(num_particles=problem.num_particles)

古典的な参考解#

参考解として、この問題を NumPyEigensolver で古典的に解くことができます。

[3]:
from qiskit_algorithms import NumPyMinimumEigensolver
from qiskit_nature.second_q.algorithms.ground_state_solvers import GroundStateEigensolver

np_solver = NumPyMinimumEigensolver()
np_groundstate_solver = GroundStateEigensolver(qubit_mapper, np_solver)

np_result = np_groundstate_solver.solve(problem)
[19]:
target_energy = np_result.total_energies[0]
print(np_result)
=== GROUND STATE ENERGY ===

* Electronic ground state energy (Hartree): -8.408630641972
  - computed part:      -8.408630641972
  - ActiveSpaceTransformer extracted energy part: 0.0
~ Nuclear repulsion energy (Hartree): 0.635012653104
> Total ground state energy (Hartree): -7.773617988868

=== MEASURED OBSERVABLES ===

  0:  # Particles: 4.000 S: 0.000 S^2: 0.000 M: 0.000

=== DIPOLE MOMENTS ===

~ Nuclear dipole moment (a.u.): [0.0  0.0  4.72431531]

  0:
  * Electronic dipole moment (a.u.): [0.0  0.0  6.45025807]
    - computed part:      [0.0  0.0  6.45025807]
    - ActiveSpaceTransformer extracted energy part: [0.0  0.0  0.0]
  > Dipole moment (a.u.): [0.0  0.0  -1.72594276]  Total: 1.72594276
                 (debye): [0.0  0.0  -4.38690851]  Total: 4.38690851

VQE#

VQEを実行するには、パラメータ化された量子回路をansatzとして使用し、古典的なオプティマイザーを選択する必要があります。ここでは,ヒューリスティックでハードウェア効率のよいansatzとSPSAオプティマイザーを選択します。

[5]:
from qiskit.circuit.library import EfficientSU2

ansatz = EfficientSU2(num_qubits=4, reps=1, entanglement="linear", insert_barriers=True)
ansatz.decompose().draw("mpl", style="iqx")
[5]:
../_images/tutorials_07_leveraging_qiskit_runtime_11_0.png
[6]:
import numpy as np
from qiskit.utils import algorithm_globals

# fix random seeds for reproducibility

np.random.seed(5)
algorithm_globals.random_seed = 5
[7]:
from qiskit_algorithms.optimizers import SPSA

optimizer = SPSA(maxiter=100)

initial_point = np.random.random(ansatz.num_parameters)

Qiskit Runtimeを使ってクラウド上でVQEを実行する前に、まずローカルでVQEを実行してみましょう。

[8]:
from qiskit_algorithms import VQE
from qiskit.primitives import Estimator

estimator = Estimator()

local_vqe = VQE(
    estimator,
    ansatz,
    optimizer,
    initial_point=initial_point,
)

local_vqe_groundstate_solver = GroundStateEigensolver(qubit_mapper, local_vqe)

local_vqe_result = local_vqe_groundstate_solver.solve(problem)
[9]:
print(local_vqe_result)
=== GROUND STATE ENERGY ===

* Electronic ground state energy (Hartree): -8.223473551005
  - computed part:      -8.223473551005
  - ActiveSpaceTransformer extracted energy part: 0.0
~ Nuclear repulsion energy (Hartree): 0.635012653104
> Total ground state energy (Hartree): -7.588460897901

=== MEASURED OBSERVABLES ===

  0:  # Particles: 3.997 S: 0.438 S^2: 0.631 M: 0.001

=== DIPOLE MOMENTS ===

~ Nuclear dipole moment (a.u.): [0.0  0.0  4.72431531]

  0:
  * Electronic dipole moment (a.u.): [0.0  0.0  1.41136787]
    - computed part:      [0.0  0.0  1.41136787]
    - ActiveSpaceTransformer extracted energy part: [0.0  0.0  0.0]
  > Dipole moment (a.u.): [0.0  0.0  3.31294744]  Total: 3.31294744
                 (debye): [0.0  0.0  8.42067168]  Total: 8.42067168

Runtime VQE#

固有値ソルバーをローカルVQEアルゴリズムからQiskit Runtimeを使用して実行されるVQEに交換しましょう。 Qiskit_nature.runtime.VQEClient によって VQE クラスを交換するだけです。

まず、Qiskit Runtimeにアクセスするためのプロバイダーをロードする必要があります。 :次のセルをあなたのプロバイダーに置き換える必要があります。

[10]:
from qiskit import IBMQ

IBMQ.load_account()
provider = IBMQ.get_provider(group="open")  # replace by your runtime provider

backend = provider.get_backend("ibmq_qasm_simulator")  # select a backend that supports the runtime

これで、 VQEClient を設定できます。この最初のリリースでは、オプティマイザーを辞書として提供する必要があります。将来のリリースでは、従来のVQEと同じオプティマイザーオブジェクトを渡すことができるようになります。

[11]:
from qiskit_nature.runtime import VQEClient

runtime_vqe = VQEClient(
    ansatz=ansatz,
    optimizer=optimizer,
    initial_point=initial_point,
    provider=provider,
    backend=backend,
    shots=1024,
    measurement_error_mitigation=True,
)  # use a complete measurement fitter for error mitigation
[12]:
runtime_vqe_groundstate_solver = GroundStateEigensolver(qubit_mapper, runtime_vqe)
runtime_vqe_result = runtime_vqe_groundstate_solver.solve(problem)
[13]:
print(runtime_vqe_result)
=== GROUND STATE ENERGY ===

* Electronic ground state energy (Hartree): -8.172591259069
  - computed part:      -8.172591259069
  - ActiveSpaceTransformer extracted energy part: 0.0
~ Nuclear repulsion energy (Hartree): 0.635012653104
> Total ground state energy (Hartree): -7.537578605965

=== MEASURED OBSERVABLES ===

  0:  # Particles: 3.988 S: 0.596 S^2: 0.951 M: 0.002

=== DIPOLE MOMENTS ===

~ Nuclear dipole moment (a.u.): [0.0  0.0  4.72431531]

  0:
  * Electronic dipole moment (a.u.): [0.0  0.0  1.25645131]
    - computed part:      [0.0  0.0  1.25645131]
    - ActiveSpaceTransformer extracted energy part: [0.0  0.0  0.0]
  > Dipole moment (a.u.): [0.0  0.0  3.467864]  Total: 3.467864
                 (debye): [0.0  0.0  8.81443024]  Total: 8.81443024

エネルギーの推移に興味がある場合、 VQEClient は、反復ごとの損失を含むオプティマイザーの履歴へアクセスすることができます(パラメーターとタイムスタンプとともに)。これは、SPSA および QN-SPSA オプティマイザー にのみ当てはまることに注意してください。 それ以外の場合は、通常の VQE と同様に、 VQEClient へのコールバックを使用する必要があります。

このデータには、基底状態ソルバーの raw_result 属性を介してアクセスできます。

[17]:
runtime_result = runtime_vqe_result.raw_result
history = runtime_result.optimizer_history
loss = history["energy"]
[20]:
import matplotlib.pyplot as plt

plt.rcParams["font.size"] = 14

# plot loss and reference value
plt.figure(figsize=(12, 6))
plt.plot(loss + runtime_vqe_result.nuclear_repulsion_energy, label="Runtime VQE")
plt.axhline(y=target_energy + 0.2, color="tab:red", ls=":", label="Target + 200mH")
plt.axhline(y=target_energy, color="tab:red", ls="--", label="Target")

plt.legend(loc="best")
plt.xlabel("Iteration")
plt.ylabel("Energy [H]")
plt.title("VQE energy");
../_images/tutorials_07_leveraging_qiskit_runtime_25_0.png
[21]:
import qiskit.tools.jupyter

%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
qiskit-terra0.23.0.dev0+f339f71
qiskit-aer0.11.1
qiskit-ibmq-provider0.19.2
qiskit-nature0.6.0
System information
Python version3.9.15
Python compilerGCC 12.2.1 20220819 (Red Hat 12.2.1-2)
Python buildmain, Oct 12 2022 00:00:00
OSLinux
CPUs8
Memory (Gb)62.499855041503906
Wed Dec 07 11:09:57 2022 CET

This code is a part of Qiskit

© Copyright IBM 2017, 2022.

This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.

Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.