注釈
このページは docs/tutorials/vqe_with_estimator.ipynb から生成されました。
Estimator primitive を使用した変分量子固有値ソルバー¶
概要¶
変分量子固有ソルバー (Variational Quantum Eigensolver、VQE) は、 ハミルトニアン の基底状態エネルギー (すなわち最小固有値) を見つけるための最適化ルーチンであり、 直近のハードウェアにとって有用性のある候補と考えられています。 このチュートリアルでは、 Estimator
primitiveを使用して変分ジョブを実行依頼するためのQiskit Runtimeの使い方を説明します。 具体的には、 \(H_2\) 分子の基底状態エネルギーを計算していきます。
ローカル開発環境のセットアップ¶
このチュートリアルでは、Qiskit Runtime Service インスタンスが必要です。まだ実行していない場合は、これらの手順 に従ってセットアップします。
分子ハミルトニアンの生成¶
Qiskit Natureを使って、分子ハミルトニアンを生成し処理します。 まだの場合は、次に示すコマンドを使って Qiskit Nature (およびPySCFアドオン) をインストールしてください。ただし、最初にこれらのパッケージをインストールする必要があります。 以下に示すコマンドを使用して、pipを介してインストールできます。 Qiskit Nature に関する詳細は、 入門ガイド を参照してください。
pip install qiskit-nature
pip install 'qiskit-nature[pyscf]'
次に、基底状態エネルギーを見つけたいハミルトニアンを生成します。 最初のステップは PySCFDriver
を使って分子を表す文字列を ElectronicStructureProblem
に変換することです。 次のステップは、 ParityMapper
を使用して、この問題を量子コンピュータ上で実行できる量子ビット・ハミルトニアンに変換します。
[1]:
from qiskit_nature.second_q.drivers import PySCFDriver
driver = PySCFDriver(
atom="H 0 0 0; H 0 0 0.72" # Two Hydrogen atoms, 0.72 Angstrom apart
)
molecule = driver.run()
from qiskit_nature.second_q.mappers import QubitConverter, ParityMapper
qubit_converter = QubitConverter(ParityMapper())
hamiltonian = qubit_converter.convert(molecule.second_q_ops()[0])
古典的な解法¶
この問題はとても小さいので、古典的な方法で正確に解けます。 以下のコードでは、VQEの性能評価に使用するため、NumPy
パッケージの最小固有ソルバーを使用して、電子の基底状態エネルギー (ハートリー単位) を求めます。
[2]:
from qiskit.algorithms.minimum_eigensolvers import NumPyMinimumEigensolver
sol = NumPyMinimumEigensolver().compute_minimum_eigenvalue(hamiltonian)
real_solution = molecule.interpret(sol)
real_solution.groundenergy
[2]:
-1.8720800636154613
VQEを用いた解法¶
次に、サービスインスタンスを作成し、バックエンドを指定します。 この例では、待ち行列の時間を避けるためにシミュレーターを使用します。 バックエンドを変更するだけで実際のデバイス上で動作させることができます
[3]:
from qiskit_ibm_runtime import QiskitRuntimeService, Estimator, Session, Options
service = QiskitRuntimeService()
backend = "ibmq_qasm_simulator"
次のコード・セルは、VQEをどのように実行するかを指定します。これは、
試行状態を作るために使用される回路 (ansatz) のタイプと、
より良い解に達するよう試行状態の調整法を決める古典的なアルゴリズムと
開始パラメーターを含みます。
また、後でプロットするために途中の結果を記録するための単純なオブジェクトを作成します。
[4]:
from qiskit.algorithms.minimum_eigensolvers import VQE
# Use RealAmplitudes circuit to create trial states
from qiskit.circuit.library import RealAmplitudes
ansatz = RealAmplitudes(num_qubits=2, reps=2)
# Search for better states using SPSA algorithm
from qiskit.algorithms.optimizers import SPSA
optimizer = SPSA(150)
# Set a starting point for reproduceability
import numpy as np
np.random.seed(6)
initial_point = np.random.uniform(-np.pi, np.pi, 12)
# Create an object to store intermediate results
from dataclasses import dataclass
@dataclass
class VQELog:
values: list
parameters: list
def update(self, count, parameters, mean, _metadata):
self.values.append(mean)
self.parameters.append(parameters)
print(f"Running circuit {count} of ~350", end="\r", flush=True)
log = VQELog([], [])
次のコード・セルは、VQEアルゴリズムを実行します。 実際のデバイスでの実行を選択した場合、このコードは最終結果に ゼロノイズの外挿 を実行してノイズの影響を推定します。 ノイズのないデバイスから得られる結果を想像してみてください。
[5]:
# Main calculation
with Session(service=service, backend=backend) as session:
options = Options()
options.optimization_level = 3
vqe = VQE(
Estimator(session=session, options=options),
ansatz,
optimizer,
callback=log.update,
initial_point=initial_point,
)
result = vqe.compute_minimum_eigenvalue(hamiltonian)
print("Experiment complete.".ljust(30))
print(f"Raw result: {result.optimal_value}")
if "simulator" not in backend:
# Run once with ZNE error mitigation
options.resilience_level = 2
vqe = VQE(
Estimator(session=session, options=options),
ansatz,
SPSA(1),
initial_point=result.optimal_point,
)
result = vqe.compute_minimum_eigenvalue(hamiltonian)
print(f"Mitigated result: {result.optimal_value}")
Experiment complete.
Raw result: -1.867238744921776
最後に、以下のコード・セルは、最適化プロセスの途中の結果をプロットします。 最適化アルゴリズムは、より低いエネルギーを生成する値に徐々になるよう、パラメーターを調整します。 アルゴリズムが局所的最小値に巻き込まれない場合、このグラフは分子の電子基底状態エネルギーでプラトーになります。
[6]:
import matplotlib.pyplot as plt
plt.rcParams["font.size"] = 14
# Plot energy and reference value
plt.figure(figsize=(12, 6))
plt.plot(log.values, label="Estimator VQE")
plt.axhline(y=real_solution.groundenergy, color="tab:red", ls="--", label="Target")
plt.legend(loc="best")
plt.xlabel("Iteration")
plt.ylabel("Energy [H]")
plt.title("VQE energy")
plt.show()
[7]:
import qiskit_ibm_runtime
qiskit_ibm_runtime.version.get_version_info()
[7]:
'0.8.0'
[10]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Qiskit Software | Version |
---|---|
qiskit-terra | 0.23.1 |
qiskit-aer | 0.11.2 |
qiskit-ibmq-provider | 0.20.0 |
qiskit | 0.41.0 |
qiskit-nature | 0.5.2 |
System information | |
Python version | 3.10.6 |
Python compiler | Clang 13.1.6 (clang-1316.0.21.2.5) |
Python build | main, Aug 11 2022 13:49:25 |
OS | Darwin |
CPUs | 8 |
Memory (Gb) | 32.0 |
Mon Feb 20 12:12:03 2023 GMT |
This code is a part of Qiskit
© Copyright IBM 2017, 2023.
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.