Spanish
Idiomas
English
Bengali
French
German
Japanese
Korean
Portuguese
Spanish
Tamil

Nota

Esta página fue generada a partir de tutorials/algorithms/01_algorithms_introduction.ipynb.

Una Introducción a los Algoritmos en Qiskit

Esta es una introducción a algoritmos en Qiskit la cual proporciona una visión general para ayudarte a entender los diversos aspectos de su funcionalidad para poder comenzar. Otros tutoriales proporcionan un material más a profundidad para algunos algoritmos y maneras de usarlos, etc.

¿Cómo está estructurada la librería de algoritmos?

Qiskit proporciona una serie de Algoritmos y están agrupados por categoría según la tarea que pueden realizar. Por ejemplo, Minimum Eigensolvers para encontrar el valor propio más pequeño de un operador, por ejemplo, la energía del estado fundamental de un Hamiltoniano químico o una solución a un problema de optimización cuando se expresa como un Hamiltoniano de Ising. Existen los Time Evolvers para la evolución temporal de los sistemas cuánticos y Amplitude Estimators para la estimación de valores que se pueden utilizar, por ejemplo, en aplicaciones financieras. El conjunto completo de categorías se puede ver en el enlace de la documentación de algoritmos mencionado anteriormente.

Los algoritmos son configurables y, a menudo, parte de la configuración será en forma de bloques de construcción más pequeños, de los cuales se pueden dar diferentes instancias del tipo de bloque de construcción. Por ejemplo, con VQE, el Variacional Quantum Eigensolver, se necesita una función de onda de prueba, en forma de un QuantumCircuit y un optimizador clásico, entre otras cosas.

Veamos un ejemplo para construir una instancia de VQE. Aquí TwoLocal es la forma variacional (función de onda de prueba), un circuito parametrizado que se puede variar y SLSQP es un optimizador clásico. Estos se crean como instancias separadas y se pasan a VQE cuando este es construido. Probar, por ejemplo, un optimizador clásico diferente o una forma variacional implica simplemente generar una nueva instancia de la que deseas y pasársela al VQE.

[1]:
from qiskit.algorithms.optimizers import SLSQP
from qiskit.circuit.library import TwoLocal

num_qubits = 2
ansatz = TwoLocal(num_qubits, "ry", "cz")
optimizer = SLSQP(maxiter=1000)

Dibujemos el ansatz para que podamos ver que es un QuantumCircuit donde θ[0] a θ[7] van a ser parámetros que serán variados, mientras que el optimizador VQE encuentra el valor propio mínimo. Volveremos a revisar los parámetros más adelante en un ejemplo.

[2]:
ansatz.decompose().draw("mpl", style="iqx")
[2]:
../../_images/tutorials_algorithms_01_algorithms_introduction_4_0.png

Pero se necesita más para poder ejecutar un algoritmo, así que, vamos a ello a continuación.

¿Cómo ejecutar un algoritmo?

Los algoritmos se basan en las primitivas para evaluar valores esperados o circuitos de muestra. Las primitivas pueden estar basadas en un simulador o dispositivo real y pueden usarse indistintamente en los algoritmos, ya que todas implementan la misma interfaz.

En el VQE, tenemos que evaluar los valores esperados, por ejemplo, podemos usar qiskit.primitives.Estimator que se obtiene con la instalación predeterminada de Qiskit Terra.

[3]:
from qiskit.primitives import Estimator

estimator = Estimator()

Este estimador utiliza una simulación de vector de estado exacta para evaluar los valores esperados. También podemos usar simuladores ruidosos y basados en iteraciones o backends reales. Para obtener más información sobre los simuladores, puedes consultar Qiskit Aer y para el hardware real Qiskit IBM Runtime.

Con todos los ingredientes listos, ahora podemos instanciar el VQE:

[4]:
from qiskit.algorithms.minimum_eigensolvers import VQE

vqe = VQE(estimator, ansatz, optimizer)

Ahora podemos llamar al método compute_mininum_eigenvalue(). Esta última es la interfaz de elección para los módulos de la aplicación, como Nature y Optimization, para que puedan funcionar indistintamente con cualquier algoritmo dentro de la categoría específica.

Un ejemplo funcional completo

Juntemos lo que hemos aprendido anteriormente y creemos un ejemplo de trabajo completo. VQE encontrará el valor propio mínimo, es decir, el valor mínimo de energía de un operador Hamiltoniano y, por lo tanto, necesitamos dicho operador para que VQE funcione. Dicho operador se da a continuación. Esto fue creado originalmente por el módulo de aplicación Nature como el Hamiltoniano para una molécula de H2 a una distancia interatómica de 0.735A. Es una suma de términos de Pauli como se muestra a continuación, pero por ahora no voy a decir nada más al respecto, ya que el objetivo es ejecutar el algoritmo, pero se puede encontrar más información sobre los operadores en otros tutoriales.

[5]:
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)
])

Ahora corramos el VQE e imprimamos el objeto que devuelve como resultado.

[6]:
result = vqe.compute_minimum_eigenvalue(H2_op)
print(result)
{   'aux_operators_evaluated': None,
    'cost_function_evals': 102,
    'eigenvalue': -1.857275020719397,
    'optimal_circuit': <qiskit.circuit.library.n_local.two_local.TwoLocal object at 0x7f96da26a470>,
    'optimal_parameters': {   ParameterVectorElement(θ[0]): -2.403507257619715,
                              ParameterVectorElement(θ[5]): 1.7060524493254914,
                              ParameterVectorElement(θ[1]): 3.085467047665086,
                              ParameterVectorElement(θ[2]): -2.1949965223522487,
                              ParameterVectorElement(θ[3]): 4.276089268519914,
                              ParameterVectorElement(θ[4]): -3.098644972035885,
                              ParameterVectorElement(θ[6]): 0.032773583818940334,
                              ParameterVectorElement(θ[7]): 2.8861019033185396},
    'optimal_point': array([-2.40350726,  3.08546705, -2.19499652,  4.27608927, -3.09864497,
        1.70605245,  0.03277358,  2.8861019 ]),
    'optimal_value': -1.857275020719397,
    'optimizer_evals': None,
    'optimizer_result': <qiskit.algorithms.optimizers.optimizer.OptimizerResult object at 0x7f96da2a4d60>,
    'optimizer_time': 0.29071593284606934}

A partir del resultado anterior, podemos ver el número de evaluaciones de la función de costo (=energía) que tomó el optimizador hasta que encontró el valor propio mínimo de \(\approx -1.85727\), que es la energía del estado fundamental electrónico de la molécula de H2 dada. También se pueden ver los parámetros óptimos del ansatz que son los valores que estaban en el ansatz en el valor mínimo.

Actualizando la primitiva dentro de VQE

Para cerrar, también cambiemos la primitiva del estimador dentro de un VQE. ¡Tal vez estés satisfecho con los resultados de la simulación y ahora quieras usar un simulador basado en iteraciones o ejecutarlo en hardware!

En este ejemplo, estamos cambiando a un estimador basado en iteraciones, aun usando la primitiva de referencia de Qiskit Terra. Sin embargo, podrías reemplazar la primitiva por, por ejemplo, el estimador de Qiskit Aer (qiskit_aer.primitives.Estimator) o incluso un backend real (qiskit_ibm_runtime.Estimator).

Para las funciones de pérdida ruidosas, el optimizador SPSA generalmente funciona bien, por lo que también actualizamos el optimizador. Consulta también el tutorial de VQE ruidoso para obtener más detalles sobre simulaciones ruidosas y basadas en iteraciones.

[7]:
from qiskit.algorithms.optimizers import SPSA

estimator = Estimator(options={"shots": 1000})

vqe.estimator = estimator
vqe.optimizer = SPSA(maxiter=100)
result = vqe.compute_minimum_eigenvalue(operator=H2_op)
print(result)
{   'aux_operators_evaluated': None,
    'cost_function_evals': 200,
    'eigenvalue': -1.8574503552440247,
    'optimal_circuit': <qiskit.circuit.library.n_local.two_local.TwoLocal object at 0x7f96da2f4250>,
    'optimal_parameters': {   ParameterVectorElement(θ[0]): -7.7940259581467375,
                              ParameterVectorElement(θ[5]): 0.28827257835035214,
                              ParameterVectorElement(θ[1]): -1.8091021117029589,
                              ParameterVectorElement(θ[2]): -2.460381278734678,
                              ParameterVectorElement(θ[3]): -7.725013961075425,
                              ParameterVectorElement(θ[4]): -1.3793338621798832,
                              ParameterVectorElement(θ[6]): -2.4148423942537587,
                              ParameterVectorElement(θ[7]): -1.8555574263247812},
    'optimal_point': array([-7.79402596, -1.80910211, -2.46038128, -7.72501396, -1.37933386,
        0.28827258, -2.41484239, -1.85555743]),
    'optimal_value': -1.8574503552440247,
    'optimizer_evals': None,
    'optimizer_result': <qiskit.algorithms.optimizers.optimizer.OptimizerResult object at 0x7f96da26a5f0>,
    'optimizer_time': 0.8142139911651611}

Nota: Aquí no fijamos la semilla aleatoria en los simuladores, por lo que volver a ejecutarlos arroja resultados ligeramente diferentes.

Con esto concluye esta introducción a los algoritmos en Qiskit. Por favor consulta los otros tutoriales de algoritmos de esta serie, para obtener una cobertura más amplia y más profunda sobre los algoritmos.

[8]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
qiskit-terra0.23.0.dev0+f52bb33
qiskit-aer0.11.1
qiskit-ignis0.7.1
qiskit-ibmq-provider0.19.2
qiskit-nature0.5.0
qiskit-optimization0.5.0
qiskit-machine-learning0.6.0
System information
Python version3.10.4
Python compilerClang 12.0.0
Python buildmain, Mar 31 2022 03:38:35
OSDarwin
CPUs4
Memory (Gb)32.0
Wed Dec 07 11:02:26 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.

[ ]: