注釈
このページは tutorials/algorithms/04_vqd.ipynb から生成されました。
変分量子収縮(Variational Quantum Deflation, VQD) アルゴリズム¶
このノートブックは、ハミルトニアンの高エネルギー状態を計算するための Variational Quantum Deflation (VQD) アルゴリズムのQiskitの実装をどのように使うかをデモしています。この 参考論文 で紹介されています。
はじめに¶
VQDは変分法を用いて、与えられた系のハミルトニアン H の k 個の固有値を求める量子アルゴリズムです。
このアルゴリズムは、一般化されたハミルトニアンの励起状態エネルギーを、修正されたコスト関数上で最適化することによって計算します。各連続固有値は、最小化されなければならない以前に計算されたすべての固有値との重複項を導入することによって、繰り返し計算されます。これにより、より高いエネルギーの固有値が発見されるようになります。
VQDの完全な動作例¶
VQDワークフローの最初のステップは、量子ビット演算子、Ansatz、オプティマイザーを作成することです。この例では、H2分子を使用します。以前のVQEチュートリアルを終了していれば、すでに見慣れた分子であるはずです。
[1]:
from qiskit.quantum_info import SparsePauliOp
H2_op = SparsePauliOp.from_list(
[
("II", -1.052373245772859),
("IZ", 0.39793742484318045),
("ZI", -0.39793742484318045),
("ZZ", -0.01128010425623538),
("XX", 0.18093119978423156),
]
)
例えば、3つの量子ビットを持つ TwoLocal
ansatzを設定し、最適化手法として SLSQP
を選択することが可能です。
[2]:
from qiskit.circuit.library import TwoLocal
from qiskit.algorithms.optimizers import SLSQP
ansatz = TwoLocal(3, rotation_blocks=["ry", "rz"], entanglement_blocks="cz", reps=1)
optimizer = SLSQP()
ansatz.decompose().draw('mpl')
[2]:

ワークフローの次のステップは VQD
を実行するために必要なprimitive を定義することです。このアルゴリズムでは、2種類のprimitive インスタンスが必要です。1つは、アルゴリズムの 「VQE part 「の期待値を計算するための Estimator
で、もう1つは Sampler
です。サンプラーは StateFidelity
のサブルーチンに渡され、高エネルギー状態のコストを計算するために使用されます。状態忠実度を計算するために使用できるメソッドはいくつかありますが、シンプルにするために、 qiskit.algorithm.state_fidelities
で既に利用できる ComputeUncompute
メソッドを使用することができます。
[3]:
from qiskit.primitives import Sampler, Estimator
from qiskit.algorithms.state_fidelities import ComputeUncompute
estimator = Estimator()
sampler = Sampler()
fidelity = ComputeUncompute(sampler)
VQDアルゴリズムをセットアップするためには、計算するエネルギー状態の数(k
)と、オリジナルのVQD論文で定義された``betas``という2つの追加入力を定義することが重要です。この例では、状態数(k
) は3つに設定され、基底状態に加えて2つの励起状態が計算されることを示しています。
betas
は,各オーバーラップ項のコスト関数への寄与度のバランスをとるもので, VQD
の構築においてオプションの引数として利用することができます。ユーザが設定しない場合は、 SparsePauliOp
型の入力演算子に対して自動評価されます。もし、独自の betas
を設定したい場合は、長さ k
の値のリストを指定してください。
[4]:
k = 3
betas = [33, 33, 33]
VQDアルゴリズムを実行する準備はほぼ整いましたが、途中の値を保存するために、まずコールバックを定義しておきましょう。
[5]:
counts = []
values = []
steps = []
def callback(eval_count, params, value, meta, step):
counts.append(eval_count)
values.append(value)
steps.append(step)
最後に VQD
のインスタンスを作成し、選択した演算子に対する固有値を計算します。
[6]:
from qiskit.algorithms.eigensolvers import VQD
vqd = VQD(estimator, fidelity, ansatz, optimizer, k=k, betas=betas, callback=callback)
result = vqd.compute_eigenvalues(operator = H2_op)
vqd_values = result.optimal_values
VQD
の結果の一部として、3つの状態のエネルギーを見ることができます。
[7]:
print(vqd_values)
[-1.85727464 -1.2445845 -0.88272229]
そして、コールバックで格納された値を用いて、各状態のエネルギー収束をプロットすることができます。
[8]:
import numpy as np
import pylab
pylab.rcParams["figure.figsize"] = (12, 8)
steps = np.asarray(steps)
counts = np.asarray(counts)
values = np.asarray(values)
for i in range(1,4):
_counts = counts[np.where(steps == i)]
_values = values[np.where(steps == i)]
pylab.plot(_counts, _values, label=f"State {i-1}")
pylab.xlabel("Eval count")
pylab.ylabel("Energy")
pylab.title("Energy convergence for each computed state")
pylab.legend(loc="upper right");

この分子は NumPyEigensolver
クラスを使って正確に解くことができ、 VQD
の結果と比較できる参照値を得ることができます。
[9]:
from qiskit.algorithms.eigensolvers import NumPyEigensolver
from qiskit.opflow import PauliSumOp
exact_solver = NumPyEigensolver(k=3)
exact_result = exact_solver.compute_eigenvalues(PauliSumOp(H2_op))
ref_values = exact_result.eigenvalues
正確な結果と、以前に計算した VQD
の固有値の比較を見てみましょう。
[10]:
print(f"Reference values: {ref_values}")
print(f"VQD values: {vqd_values}")
Reference values: [-1.85727503 -1.24458455 -0.88272215]
VQD values: [-1.85727464 -1.2445845 -0.88272229]
ご覧のように、VQDの結果は厳密解からの値と一致し、VQEを拡張して励起状態も計算できるようになりました。
[11]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Qiskit Software | Version |
---|---|
qiskit-terra | 0.22.2 |
qiskit-aer | 0.11.1 |
qiskit-ignis | 0.7.1 |
qiskit-ibmq-provider | 0.19.2 |
qiskit | 0.39.2 |
System information | |
Python version | 3.10.2 |
Python compiler | Clang 13.0.0 (clang-1300.0.29.30) |
Python build | v3.10.2:a58ebcc701, Jan 13 2022 14:50:16 |
OS | Darwin |
CPUs | 8 |
Memory (Gb) | 64.0 |
Fri Dec 09 14:27:13 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.