Note
Cette page a été générée à partir de tutorials/chemistry/05_Sampling_potential_energy_surfaces.ipynb.
Exécuter en mode interactif dans le IBM Quantum lab.
Échantillonnage de la surface d’énergie potentielle¶
Introduction¶
Ce bloc-notes (notebook
) interactif montre comment utiliser l’algorithme d’échantillonneurs potentiels d’énergie Surface (Potential Energy Surface
ou PES) de la chimie qiskit pour générer le profil de dissociation d’une molécule. Nous utilisons la surface d’énergie potentielle de Born-Oppenhemier (Born-Oppenheimer Potential Energy Surface
ou BOPES) et nous démontrons comment exploiter le bootstrap et l’extrapolation pour réduire le nombre total d’évaluations de fonctions dans le calcul du PSE à l’aide du Variational Quantum Eigensolver (VQE).
[1]:
# import common packages
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from functools import partial
# qiskit
from qiskit.aqua import QuantumInstance
from qiskit import BasicAer
from qiskit.aqua.algorithms import NumPyMinimumEigensolver, VQE, IQPE
from qiskit.aqua.components.optimizers import SLSQP
from qiskit.circuit.library import ExcitationPreserving
from qiskit import BasicAer
from qiskit.aqua.algorithms import NumPyMinimumEigensolver, VQE
from qiskit.aqua.components.optimizers import SLSQP
# chemistry components
from qiskit.chemistry.components.initial_states import HartreeFock
from qiskit.chemistry.components.variational_forms import UCCSD
from qiskit.chemistry.drivers import PySCFDriver, UnitsType
from qiskit.chemistry.core import Hamiltonian, TransformationType, QubitMappingType
from qiskit.aqua.algorithms import VQAlgorithm, VQE, MinimumEigensolver
from qiskit.chemistry.transformations import FermionicTransformation
from qiskit.chemistry.drivers import PySCFDriver
from qiskit.chemistry.algorithms.ground_state_solvers import GroundStateEigensolver
from qiskit.chemistry.algorithms.pes_samplers.bopes_sampler import BOPESSampler
from qiskit.chemistry.drivers.molecule import Molecule
from qiskit.chemistry.algorithms.pes_samplers.extrapolator import *
import warnings
warnings.simplefilter('ignore', np.RankWarning)
Ici, nous utilisons la molécule H2 comme système modèle de test.
[2]:
ft = FermionicTransformation()
driver = PySCFDriver()
solver = VQE(quantum_instance=
QuantumInstance(backend=BasicAer.get_backend('statevector_simulator')))
me_gsc = GroundStateEigensolver(ft, solver)
[3]:
stretch1 = partial(Molecule.absolute_stretching, atom_pair=(1, 0))
mol = Molecule(geometry=[('H', [0., 0., 0.]),
('H', [0., 0., 0.3])],
degrees_of_freedom=[stretch1],
)
# pass molecule to PSYCF driver
driver = PySCFDriver(molecule=mol)
[4]:
print(mol.geometry)
[('H', [0.0, 0.0, 0.0]), ('H', [0.0, 0.0, 0.3])]
Faire une perturbation à la molécule le long de la dof absolute_stretching¶
[5]:
mol.perturbations = [0.2]
print(mol.geometry)
mol.perturbations = [0.6]
print(mol.geometry)
[('H', [0.0, 0.0, 0.0]), ('H', [0.0, 0.0, 0.5])]
[('H', [0.0, 0.0, 0.0]), ('H', [0.0, 0.0, 0.8999999999999999])]
Calculer le profil de dissociation de la liaison (bond
) à l’aide de BOPES Sampler¶
Ici, nous passons l’information moléculaire et le VQE à un type intégré appelé le BOPES Sampler. L’échantillonneur (Sampler
) BOPES permet le calcul de la surface d’énergie potentielle pour un ensemble déterminé de degrés de liberté/points d’intérêt.
D’abord, nous comparons ´´pas de bootstrapping ´´vs ´´bootstrapping¶
Bootstrapping the BOPES sampler involves utilizing the optimal variational parameters for a given degree of freedom, say r (ex. interatomic distance) as the initial point for VQE at a later degree of freedom, say r + \(\epsilon\). By default, if bootstrapping is set to True, all previous optimal parameters are used as initial points for the next runs.
[7]:
distance1 = partial(Molecule.absolute_distance, atom_pair=(1, 0))
mol = Molecule(geometry=[('H', [0., 0., 0.]),
('H', [0., 0., 0.3])],
degrees_of_freedom=[distance1],
)
# pass molecule to PSYCF driver
driver = PySCFDriver(molecule=mol)
# Specify degree of freedom (points of interest)
points = np.linspace(0.25, 2, 30)
results_full = {} # full dictionary of results for each condition
results = {} # dictionary of (point,energy) results for each condition
conditions = {False: 'no bootstrapping', True: 'bootstrapping'}
for value, bootstrap in conditions.items():
# define instance to sampler
bs = BOPESSampler(
gss=me_gsc
,bootstrap=value
,num_bootstrap=None
,extrapolator=None)
# execute
res = bs.sample(driver,points)
results_full[f'{bootstrap}'] = res.raw_results
results[f'points_{bootstrap}'] = res.points
results[f'energies_{bootstrap}'] = res.energies
Comparer avec eigensolver classique¶
[8]:
# define numpy solver
solver_numpy = NumPyMinimumEigensolver()
me_gsc_numpy = GroundStateEigensolver(ft, solver_numpy)
bs_classical = BOPESSampler(
gss=me_gsc_numpy
,bootstrap=False
,num_bootstrap=None
,extrapolator=None)
# execute
res_np = bs_classical.sample(driver, points)
results_full['np'] = res_np.raw_results
results['points_np'] = res_np.points
results['energies_np'] = res_np.energies
Tracer (Plot
) les résultats¶
[9]:
fig = plt.figure()
for value, bootstrap in conditions.items():
plt.plot(results[f'points_{bootstrap}'], results[f'energies_{bootstrap}'], label = f'{bootstrap}')
plt.plot(results['points_np'], results['energies_np'], label = 'numpy')
plt.legend()
plt.title('Dissociation profile')
plt.xlabel('Interatomic distance')
plt.ylabel('Energy')
[9]:
Text(0, 0.5, 'Energy')

Comparer le nombre d’évaluations¶
[10]:
for condition, result_full in results_full.items():
print(condition)
print('Total evaluations for ' + condition + ':')
sum = 0
for key in result_full:
if condition is not 'np':
sum += result_full[key]['raw_result']['cost_function_evals']
else:
sum = 0
print(sum)
no bootstrapping
Total evaluations for no bootstrapping:
2931
bootstrapping
Total evaluations for bootstrapping:
991
np
Total evaluations for np:
0
Extrapolation¶
Ici, un extrapolator est ajouté, qui essaiera de s’adapter à chacun (param, point) défini à une fonction spécifiée, et suggère un paramètre initial défini pour le point suivant (degré de liberté).
Extrapolator est basé sur un extrapolator externe qui fixe la « fenêtre » (´´window´´), c’est-à-dire le nombre de points précédents à utiliser pour l’extrapolation, tandis que l’extrapolator interne procède à l’extrapolation réelle.
En pratique, l’utilisateur définit la fenêtre (
window
) en spécifiant une valeur entière à num_bootstrap - qui est également le nombre de points précédents à utiliser pour le bootstrap. En outre, l’extrapolation externe définit l’espace dans la manière d’extrapoler - ici PCA, la mise en cluster et l’approche standard des fenêtres (standard windows approach
).
En pratique, si aucune extrapolation n’est définie et que le bootstrap est True, tous les points précédents seront bootstrapped. Si une liste d’extrapolateurs est définie et qu’aucun point n’est spécifié pour le bootstrap, l’extrapolation sera effectuée en fonction de tous les points précédents.
Extrapolateur de fenêtre (
Window Extraplotor
): un extrapolateur qui encapsule une autre extrapolation, limitant la valeur du paramètre de vérité du sol (ground truth parameter
) de l’extrapolateur interne à une taille de fenêtre fixeExtrapolator PCA: une extrapolation de l’encapsuleur (
wrapper
) qui réduit la dimensionnalité des points avec la PCA, effectue une extrapolation dans l’espace de PCA transformé, et détransforme les résultats avant de retourner.Extrapolator Sieve: un extrapolator d’encapsuleur (
wrapper
) qui effectue une extrapolation, puis regroupe les valeurs extrapolées des paramètres en deux grands et petits groupes (clusters
), et définit les paramètres des petits groupes à zéro.Extrapolateur Polynomial: extrapolateur basé sur l’ajustement de chaque paramètre à une fonction polynomiale d’un degré spécifié par l’utilisateur.
Extrapolateur Différentiel: une extrapolation basée sur le traitement de chaque ensemble de paramètres comme un point dans l’espace, et une régression permettant de prédire le paramètre défini pour le point suivant. Un degré spécifié par l’utilisateur ajoute également des dérivées aux valeurs des vecteurs de points qui servent comme caractéristiques dans les données de formation (
training
) pour la régression linéaire.
Nous testons ici deux techniques d’extrapolation différentes¶
[11]:
# define different extrapolators
degree = 1
extrap_poly = Extrapolator.factory("poly", degree = degree)
extrap_diff = Extrapolator.factory("diff_model", degree = degree)
extrapolators = {'poly': extrap_poly, 'diff_model': extrap_diff}
for key in extrapolators:
extrap_internal = extrapolators[key]
extrap = Extrapolator.factory("window", extrapolator = extrap_internal)
# define extrapolator
# BOPES sampler
bs_extr = BOPESSampler(
gss=me_gsc
,bootstrap=True
,num_bootstrap=None
,extrapolator=extrap)
# execute
res = bs_extr.sample(driver, points)
results_full[f'{key}']= res.raw_results
results[f'points_{key}'] = res.points
results[f'energies_{key}'] = res.energies
Tracer (Plot
) les résultats¶
[12]:
fig = plt.figure()
for value, bootstrap in conditions.items():
plt.plot(results[f'points_{bootstrap}'], results[f'energies_{bootstrap}'], label = f'{bootstrap}')
plt.plot(results['points_np'], results['energies_np'], label = 'numpy')
for condition in extrapolators.keys():
print(condition)
plt.plot(results[f'points_{condition}'], results[f'energies_{condition}'], label = condition)
plt.legend()
plt.title('Dissociation profile')
plt.xlabel('Interatomic distance')
plt.ylabel('Energy')
poly
diff_model
[12]:
Text(0, 0.5, 'Energy')

Comparer le nombre d’évaluations¶
[13]:
for condition, result_full in results_full.items():
print(condition)
print('Total evaluations for ' + condition + ':')
sum = 0
for key in results_full[condition].keys():
if condition is not 'np':
sum += results_full[condition][key]['raw_result']['cost_function_evals']
else:
sum = 0
print(sum)
no bootstrapping
Total evaluations for no bootstrapping:
2931
bootstrapping
Total evaluations for bootstrapping:
991
np
Total evaluations for np:
0
poly
Total evaluations for poly:
563
diff_model
Total evaluations for diff_model:
1089
[14]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Qiskit Software | Version |
---|---|
Qiskit | 0.23.6 |
Terra | 0.16.4 |
Aer | 0.7.5 |
Ignis | 0.5.2 |
Aqua | 0.8.2 |
IBM Q Provider | 0.11.1 |
System information | |
Python | 3.8.6 | packaged by conda-forge | (default, Jan 25 2021, 23:21:18) [GCC 9.3.0] |
OS | Linux |
CPUs | 8 |
Memory (Gb) | 31.409000396728516 |
Tue Feb 23 18:07:35 2021 UTC |
This code is a part of Qiskit
© Copyright IBM 2017, 2021.
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.
[ ]: