French
Langues
English
Japanese
German
Korean
Portuguese, Brazilian
French
Shortcuts

Note

Cette page a été générée à partir de tutorials/algorithms/02_vqe_convergence.ipynb.

Exécuter en mode interactif dans le IBM Quantum lab <https://quantum-computing.ibm.com/jupyter/tutorial/algorithms/02_vqe_convergence.ipynb> _.

Surveillance de la convergence VQE

Les algorithmes variationnels de Qiskit, tels que VQE <https://qiskit.org/documentation/stubs/qiskit.aqua.algorithms.VQE.html> __ et QAOA <https://qiskit.org/documentation/stubs/qiskit.aqua.algorithms.QAOA.html> __, permettent à un utilisateur de fournir une méthode de rappel (callback) qui peut être utilisée pour surveiller la progression de l’optimisation lorsque l’algorithme s’exécute et converge vers le minimum. Le callback est appelé pour chaque évaluation fonctionnelle par l’optimiseur et fournit la valeur de l’optimiseur en cours, le nombre d’évaluations, les paramètres de l’optimiseur, etc. Notez que, selon l’optimiseur spécifique, il ne s’agit pas de chaque itération (étape) de l’optimiseur. Par exemple, si l’optimiseur appelle la fonction de coût pour calculer un gradient basé sur les différences finies, cela sera visible via le callback.

Ce notebook montre l’utilisation de l’algorithme VQE de Qiskit pour tracer des graphiques du chemin de convergence vers l’énergie de l’état fondamental avec un ensemble sélectionné d’optimiseurs.

[1]:
import numpy as np
import pylab

from qiskit import BasicAer
from qiskit.aqua.operators import X, Z, I
from qiskit.aqua import QuantumInstance, aqua_globals
from qiskit.aqua.algorithms import VQE, NumPyMinimumEigensolver
from qiskit.aqua.components.initial_states import Zero
from qiskit.aqua.components.optimizers import COBYLA, L_BFGS_B, SLSQP
from qiskit.circuit.library import TwoLocal

Tout d’abord, nous créons un opérateur pour VQE. Ici nous utiliserons le même opérateur que celui qui a été utilisé dans l’introduction des algorithmes, et initialement calculé par Qiskit Chemistry pour une molécule H2.

[2]:
H2_op = (-1.052373245772859 * I ^ I) + \
        (0.39793742484318045 * I ^ Z) + \
        (-0.39793742484318045 * Z ^ I) + \
        (-0.01128010425623538 * Z ^ Z) + \
        (0.18093119978423156 * X ^ X)

Nous allons montrer l’utilisation d’une fonction de rappel (callback) ci-dessous sur un ensemble d’optimiseurs afin de comparer. L’énergie minimale du Hamiltonien H2 peut être trouvée assez facilement, donc nous sommes en mesure de régler le paramètre maxiters à une petite valeur

[3]:
optimizers = [COBYLA(maxiter=80), L_BFGS_B(maxiter=60), SLSQP(maxiter=60)]
converge_cnts = np.empty([len(optimizers)], dtype=object)
converge_vals = np.empty([len(optimizers)], dtype=object)

for i, optimizer in enumerate(optimizers):
    print('\rOptimizer: {}        '.format(type(optimizer).__name__), end='')
    aqua_globals.random_seed = 50
    var_form = TwoLocal(rotation_blocks='ry', entanglement_blocks='cz')

    counts = []
    values = []
    def store_intermediate_result(eval_count, parameters, mean, std):
        counts.append(eval_count)
        values.append(mean)

    vqe = VQE(H2_op, var_form, optimizer, callback=store_intermediate_result,
              quantum_instance=QuantumInstance(backend=BasicAer.get_backend('statevector_simulator')))
    result = vqe.compute_minimum_eigenvalue(operator=H2_op)
    converge_cnts[i] = np.asarray(counts)
    converge_vals[i] = np.asarray(values)
print('\rOptimization complete      ');
Optimization complete

Maintenant, à partir des données de callback que nous avons stockées, nous pouvons tracer la valeur d’énergie à chaque appel de fonction objectif que chaque optimiseur fait. Un optimiseur utilisant une méthode de différence finie pour le calcul du gradient a ce tracé avec des plateaux caractéristique où, pour un certain nombre d’évaluations consécutives, il calcule la valeur d’énergie pour des points très proches (les points très proches ayant des valeurs d’énergie très similaires, la différence ne peut être vue sur l’échelle du graphique).

[4]:
pylab.rcParams['figure.figsize'] = (12, 8)
for i, optimizer in enumerate(optimizers):
    pylab.plot(converge_cnts[i], converge_vals[i], label=type(optimizer).__name__)
pylab.xlabel('Eval count')
pylab.ylabel('Energy')
pylab.title('Energy convergence for various optimizers')
pylab.legend(loc='upper right');
../../_images/tutorials_algorithms_02_vqe_convergence_7_0.png

Enfin, puisque le problème ci-dessus est toujours facilement calculable classiquement, nous pouvons utiliser NumPyMinimumEigensolver pour calculer une valeur de référence très proche de la solution exacte. Nous pouvons maintenant tracer la différence entre la solution exacte et les valeurs obtenues lors des itérations de l’optimiseur, car avec VQE l’énergie converge vers la valeur minimale qui devrait être la solution exacte obtenue classiquement.

[5]:
npme = NumPyMinimumEigensolver()
result = npme.compute_minimum_eigenvalue(operator=H2_op)
ref_value = result.eigenvalue.real
print(f'Reference value: {ref_value:.5f}')
Reference value: -1.85728
[6]:
pylab.rcParams['figure.figsize'] = (12, 8)
for i, optimizer in enumerate(optimizers):
    pylab.plot(converge_cnts[i], abs(ref_value - converge_vals[i]), label=type(optimizer).__name__)
pylab.xlabel('Eval count')
pylab.ylabel('Energy difference from solution reference value')
pylab.title('Energy convergence for various optimizers')
pylab.yscale('log')
pylab.legend(loc='upper right');
../../_images/tutorials_algorithms_02_vqe_convergence_10_0.png

Utilisation de l’infrastructure Gradient

Qiskit dispose désormais d’une structure Gradient dans le cadre de la fonctionnalité Opérateur. Avec le gradient calculé pour l’optimiseur, nous ne voyons maintenant que les étapes d’optimisation elles-mêmes.

[7]:
from qiskit.aqua.operators.gradients import Gradient

aqua_globals.random_seed = 50
var_form = TwoLocal(rotation_blocks='ry', entanglement_blocks='cz')

optimizer = SLSQP(maxiter=60)

counts = []
values = []
def store_intermediate_result(eval_count, parameters, mean, std):
    counts.append(eval_count)
    values.append(mean)

vqe = VQE(H2_op, var_form, optimizer, callback=store_intermediate_result,
          gradient=Gradient(grad_method='fin_diff'),
          quantum_instance=QuantumInstance(backend=BasicAer.get_backend('statevector_simulator')))
result = vqe.compute_minimum_eigenvalue(operator=H2_op)
print(f'Value using Gradient: {result.eigenvalue.real:.5f}')
Value using Gradient: -1.85728
[8]:
pylab.rcParams['figure.figsize'] = (12, 8)
pylab.plot(counts, values, label=type(optimizer).__name__)
pylab.xlabel('Eval count')
pylab.ylabel('Energy')
pylab.title('Energy convergence using Gradient')
pylab.legend(loc='upper right');
../../_images/tutorials_algorithms_02_vqe_convergence_13_0.png

Surveillance via la journalisation

Une grande partie du code est instrumentalisée avec des instructions Python logging. La journalisation est configurable pour ajuster le niveau de détails, etc. Un moyen facile d’activer la journalisation dans le module qiskit.aqua est d’exécuter le code suivant, où nous définissons ici le niveau de journalisation à INFO

[9]:
import logging
from qiskit.aqua import set_qiskit_aqua_logging


set_qiskit_aqua_logging(logging.INFO)

et au niveau de journalisation INFO, VQE inclura des informations sur les évaluations d’énergie, comme ci-dessous.

020-11-04 16:55:33,450:qiskit.aqua.algorithms.minimum_eigen_solvers.vqe:INFO: Energy evaluation returned [-8.88931977] - 6801.61572 (ms), eval count: 1 2020-11-04 16:55:34,463:qiskit.aqua.algorithms.minimum_eigen_solvers.vqe:INFO: Energy evaluation returned [-8.88931977] - 1012.12025 (ms), eval count: 2 2020-11-04 16:55:35,483:qiskit.aqua.algorithms.minimum_eigen_solvers.vqe:INFO: Energy evaluation returned [-8.88931977] - 1019.99474 (ms), eval count: 3 2020-11-04 16:55:36,646:qiskit.aqua.algorithms.minimum_eigen_solvers.vqe:INFO: Energy evaluation returned [-8.88931977] - 1162.09555 (ms), eval count: 4

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

Version Information

Qiskit SoftwareVersion
Qiskit0.23.0
Terra0.16.0
Aer0.7.0
Ignis0.5.0
Aqua0.8.0
IBM Q Provider0.11.0
System information
Python3.6.1 |Continuum Analytics, Inc.| (default, May 11 2017, 13:09:58) [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]
OSLinux
CPUs1
Memory (Gb)5.827335357666016
Sat Nov 07 16:21:19 2020 EST

This code is a part of Qiskit

© Copyright IBM 2017, 2020.

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.

[ ]: