Portuguese
Idiomas
English
Bengali
French
German
Japanese
Korean
Portuguese
Spanish
Tamil

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]:
../../_images/tutorials_algorithms_04_vqd_6_0.png

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");
../../_images/tutorials_algorithms_04_vqd_18_0.png

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 SoftwareVersion
qiskit-terra0.22.2
qiskit-aer0.11.1
qiskit-ignis0.7.1
qiskit-ibmq-provider0.19.2
qiskit0.39.2
System information
Python version3.10.2
Python compilerClang 13.0.0 (clang-1300.0.29.30)
Python buildv3.10.2:a58ebcc701, Jan 13 2022 14:50:16
OSDarwin
CPUs8
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.