Spanish
Idiomas
English
Bengali
French
German
Japanese
Korean
Portuguese
Spanish
Tamil

Nota

Esta página fue generada a partir de tutorials/algorithms/04_vqd.ipynb.

Algoritmo de Deflación Cuántica Variacional (VQD, Variational Quantum Deflation)

Este cuaderno demuestra cómo usar la implementación de Qiskit del algoritmo Deflación Cuántica Variacional (VQD, Variational Quantum Deflation) para calcular estados de energía más altos de un Hamiltoniano, tal como se presenta en este artículo de referencia.

Introducción

VQD es un algoritmo cuántico que utiliza una técnica variacional para encontrar los valores propios k del Hamiltoniano H de un sistema dado.

El algoritmo calcula las energías del estado excitado de los Hamiltonianos generalizados optimizando una función de costo modificada. Cada valor propio sucesivo se calcula iterativamente introduciendo un término superpuesto con todos los estados propios calculados previamente que deben minimizarse. Esto asegura que se encuentren estados propios de mayor energía.

Ejemplo práctico completo para VQD

El primer paso del flujo de trabajo de VQD es crear un operador de qubit, un ansatz y un optimizador. Para este ejemplo, puedes usar la molécula H2, que ya te resultará familiar si completaste los tutoriales anteriores de 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),
    ]
)

Puedes configurar, por ejemplo, un ansatz TwoLocal con tres qubits y elegir SLSQP como método de optimización.

[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

El siguiente paso del flujo de trabajo es definir las primitivas requeridas para ejecutar VQD. Este algoritmo requiere dos instancias primitivas diferentes: un Estimator para calcular los valores esperados para la «parte VQE» del algoritmo y un Sampler. El sampler se pasará a la subrutina StateFidelity que se usará para calcular el costo de los estados de mayor energía. Hay varios métodos que puedes usar para calcular las fidelidades de estado, pero para simplificar las cosas, puedes usar el método ComputeUncompute ya disponible en 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 el algoritmo VQD, es importante definir dos entradas adicionales: el número de estados de energía a calcular (k) y las betas definidas en el artículo original de VQD. En este ejemplo, el número de estados (k) se establecerá en tres, lo que indica que se calcularán dos estados excitados además del estado fundamental.

Las betas equilibran la contribución de cada término superpuesto a la función de costo, y son un argumento opcional en la construcción de VQD. Si el usuario no los configura, pueden autoevaluarse para operadores de entrada de tipo SparsePauliOp. Ten en cuenta que si deseas configurar tus propias betas, debes proporcionar una lista de valores de longitud k.

[4]:
k = 3
betas = [33, 33, 33]

Estás casi listo para ejecutar el algoritmo VQD, pero primero definamos una devolución de llamada para almacenar valores intermedios:

[5]:
counts = []
values = []
steps = []

def callback(eval_count, params, value, meta, step):
    counts.append(eval_count)
    values.append(value)
    steps.append(step)

Finalmente puedes instanciar VQD y calcular los valores propios para el operador elegido.

[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

Puedes ver las tres energías del estado como parte del resultado de VQD:

[7]:
print(vqd_values)
[-1.85727464 -1.2445845  -0.88272229]

Y podemos usar los valores almacenados por la devolución de llamada para graficar la convergencia de energía 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 puede ser resuelta exactamente usando la clase NumPyEigensolver, que dará un valor de referencia que puedes comparar con el resultado de 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

Veamos una comparación del resultado exacto con los valores propios de VQD previamente calculados:

[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 puedes ver, el resultado de VQD coincide con los valores de la solución exacta y extiende VQE para calcular también los 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.