Bemerkung
Diese Seite wurde aus tutorials/circuits_advanced/1_advanced_circuits.ipynb generiert.
Variational Quantum Deflation (VQD) Algorithmus¶
This notebook demostrates how to use Qiskit’s implementation of the Variational Quantum Deflation (VQD) algorithm for computing higher energy states of a Hamiltonian, as introduced in this reference paper.
Einführung¶
VQD ist ein Quantenalgorithmus, der eine Variationsmethode verwendet, um die k Eigenwerte des Hamiltonian H eines gegebenen Systems zu finden.
Der Algorithmus berechnet die angeregten Zustandsenergien von verallgemeinerten Hamiltonian durch Optimierung über eine modifizierte Kostenfunktion. Jeder aufeinanderfolgende Eigenwert wird iterativ berechnet, indem ein Überlappungsterm mit allen zuvor berechneten Eigenzuständen, die minimiert werden müssen, eingeführt wird. Dadurch wird sichergestellt, dass Eigenzustände mit höherer Energie gefunden werden.
Vollständiges Funktionsbeispiel für VQD¶
Der erste Schritt des VQD-Arbeitsablaufs besteht darin, einen Qubit-Operator, einen Ansatz und einen Optimierer zu erstellen. Für dieses Beispiel können Sie das H2-Molekül verwenden, das Ihnen bereits bekannt vorkommen sollte, wenn Sie die vorherigen VQE-Tutorials absolviert haben:
[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),
]
)
Sie können z. B. einen TwoLocal
-Ansatz mit drei Qubits aufstellen und SLSQP
als Optimierungsmethode wählen.
[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]:

The next step of the workflow is to define the required primitives for running VQD
. This algorithm requires two different primitive instances: one Estimator
for computing the expectation values for the „VQE part“ of the algorithm, and one Sampler
. The sampler will be passed along to the StateFidelity
subroutine that will be used to compute the cost for higher energy states. There are several methods that you can use to compute state fidelities, but to keep things simple, you can
use the ComputeUncompute
method already available in qiskit.algorithm.state_fidelities
.
[3]:
from qiskit.primitives import Sampler, Estimator
from qiskit.algorithms.state_fidelities import ComputeUncompute
estimator = Estimator()
sampler = Sampler()
fidelity = ComputeUncompute(sampler)
Um den VQD-Algorithmus einzurichten, ist es wichtig, zwei zusätzliche Eingaben zu definieren: die Anzahl der zu berechnenden Energiezustände (k
) und die Betas
, die in der ursprünglichen VQD-Veröffentlichung definiert wurden. In diesem Beispiel wird die Anzahl der Zustände (k
) auf drei gesetzt, was bedeutet, dass zusätzlich zum Grundzustand zwei angeregte Zustände berechnet werden.
Die betas
gleichen den Beitrag jedes Überlappungsterms zur Kostenfunktion aus und sind ein optionales Argument in der VQD
Konstruktion. Wenn sie nicht vom Benutzer gesetzt werden, können sie für Eingabeoperatoren vom Typ SparsePauliOp
automatisch ausgewertet werden. Bitte beachten Sie, dass Sie, wenn Sie Ihre eigenen betas
setzen wollen, eine Liste von Werten der Länge k
bereitstellen sollten.
[4]:
k = 3
betas = [33, 33, 33]
You are almost ready to run the VQD algorithm, but let’s define a callback first to store intermediate values:
[5]:
counts = []
values = []
steps = []
def callback(eval_count, params, value, meta, step):
counts.append(eval_count)
values.append(value)
steps.append(step)
Schließlich kann man VQD
instanziieren und die Eigenwerte für den gewählten Operator berechnen.
[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
Sie können die drei Zustandsenergien als Teil des VQD
-Ergebnisses sehen:
[7]:
print(vqd_values)
[-1.85727464 -1.2445845 -0.88272229]
Und wir können die durch den Callback gespeicherten Werte verwenden, um die Energiekonvergenz für jeden Zustand darzustellen:
[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");

Dieses Molekül kann mit der Klasse NumPyEigensolver
exakt gelöst werden, was einen Referenzwert ergibt, den man mit dem VQD
-Ergebnis vergleichen kann:
[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
Let’s see a comparison of the exact result with the previously computed VQD
eigenvalues:
[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]
Wie Sie sehen können, stimmt das Ergebnis von VQD mit den Werten der exakten Lösung überein und erweitert VQE, um auch angeregte Zustände zu berechnen.
[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.