Nota
Esta página foi gerada, a partir de tutorials/algorithms/04_vqd.ipynb.
Algoritmo de Deflação Quântica Variacional (VQD)¶
Este notebook mostra como usar a implementação do Qiskit do algoritmo Variational Quantum Deflation (VQD) para calcular estados de energia mais altos de um hamiltoniano, conforme apresentado neste documento de referência.
Introdução¶
VQD é um algoritmo quântico que usa uma técnica variacional para encontrar os autovalores k do hamiltoniano H de um determinado sistema.
O algoritmo calcula as energias do estado excitado de hamiltonianos generalizados otimizando sobre uma função de custo modificada. Cada autovalor sucessivo é calculado iterativamente pela introdução de um termo de sobreposição com todos os autoestados previamente calculados que devem ser minimizados. Isso garante que auto-estados de maior energia sejam encontrados.
Exemplo de trabalho completo para VQD¶
A primeira etapa do fluxo de trabalho VQD é criar um operador qubit, ansatz e otimizador. Para este exemplo, você pode usar a molécula H2, que já deve parecer familiar se você tiver concluído os tutoriais VQE anteriores:
[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),
]
)
Você pode configurar, por exemplo, um ansatz TwoLocal
com três qubits e escolher SLSQP
como método de otimização.
[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]:

A próxima etapa do fluxo é definir as primitivas necessárias para executar o VQD
. Este algoritmo requer duas instâncias primitivas diferentes: uma Estimator
para calcular os valores esperados para a “parte VQE” do algoritmo, e uma Sampler
. O amostrador será passado para a sub-rotina StateFidelity
que será usada para calcular o custo para estados de energia mais altos. Existem vários métodos que você pode usar para calcular fidelidades de estado, mas para simplificar, você pode usar o método ComputeUncompute
já disponível em 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)
Para configurar o algoritmo VQD, é importante definir duas entradas adicionais: o número de estados de energia a serem computados (k
) e os betas
definidos no artigo original do VQD. Neste exemplo, o número de estados (k
) será definido como três, o que indica que dois estados excitados serão computados além do estado fundamental.
Os betas
equilibram a contribuição de cada termo de sobreposição para a função de custo e são um argumento opcional na construção do VQD
. Se não forem definidos pelo usuário, eles podem ser avaliados automaticamente para operadores de entrada do tipo SparsePauliOp
. Por favor, note que se você quiser definir seus próprios betas
, você deve fornecer uma lista de valores de comprimento k
.
[4]:
k = 3
betas = [33, 33, 33]
Você está quase pronto(a) para executar o algoritmo VQD, mas primeiro vamos definir um callback para armazenar valores intermediários:
[5]:
counts = []
values = []
steps = []
def callback(eval_count, params, value, meta, step):
counts.append(eval_count)
values.append(value)
steps.append(step)
Você pode finalmente instanciar VQD
e calcular os autovalores para o operador escolhido.
[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
Você pode ver as três energias de estado como parte do resultado VQD
:
[7]:
print(vqd_values)
[-1.85727464 -1.2445845 -0.88272229]
E podemos usar os valores armazenados pelo retorno de chamada para plotar a convergência de energia para cada estado:
[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");

Esta molécula pode ser resolvida exatamente usando a classe NumPyEigensolver
, que fornecerá um valor de referência que você pode comparar com o resultado 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
Vamos ver uma comparação do resultado exato com os autovalores VQD
calculados anteriormente:
[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]
Como você pode ver, o resultado do VQD corresponde aos valores da solução exata e estende o VQE para também computar estados excitados.
[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.