Portuguese, Brazilian
Idiomas
English
Japanese
German
Korean
Portuguese, Brazilian
French
Shortcuts

Nota

Esta página foi gerada a partir do tutorials/chemistry/05_Sampling_potential_energy_surfaces.ipynb.

Execute interativamente no IBM Quantum lab.

Amostrando a superfície de energia potencial

Introdução

Este notebook interativo demonstra como utilizar o algoritmo de amostragem de Superfície de Energia Potencial (PES) do qiskit chemistry para gerar o perfil de dissociação de uma molécula. Utilizamos a Superfície de Energia Potencial de Born-Oppenhemier (BOPES) e demonstramos como explorar bootstrapping e extrapolação para reduzir o número total de avaliações de função na computação do PES usando o 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)

Aqui, utilizamos a molécula de H2 como um sistema modelo para testes.

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

Perturbe a molécula ao longo do grau de liberdade 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])]

Calcular o perfil de dissociação de ligações usando o amostrador BOPES

Aqui, passamos as informações moleculares e o VQE para um tipo interno chamado de BOPES Sampler. O BOPES Sampler permite a computação da superfície de energia potencial para um conjunto especificado de graus de liberdade/pontos de interesse.

Primeiro comparamos nenhum 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

Comparando com o eigensolver clássico

[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

Visualizando os resultados

[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')
../../_images/tutorials_chemistry_05_Sampling_potential_energy_surfaces_15_1.png

Comparando o número de avaliações

[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

Extrapolação

Aqui, um extrapolador adicionado que tentará ajustar cada conjunto (param, ponto) para alguma função especificada e sugerir um conjunto parâmetros inicial para o próximo ponto (grau de liberdade).

  • O extrapolador é baseado em um extrapolador externo que configura a ‘janela’, ou seja, o número de pontos anteriores a usar para a extrapolação, enquanto que o extrapolador interno procede com a extrapolação real.

  • Na prática, o usuário define a janela especificando um valor inteiro para num_bootstrap - que é também o número de pontos anteriores que serão usados para bootstrapping. Adicionalmente, o extrapolador externo define o espaço dentro de como extrapolar - aqui PCA, clusterização e a abordagem de janela padrão.

Na prática, se nenhum extrapolador for definido e o bootstrapping for True, então haverá o bootstrap em todos os pontos anteriores. Se uma lista de extrapoladores for definida e nenhum ponto for especificado para o bootstrap, então a extrapolação será feita com base em todos os pontos anteriores.

  1. Extrapolador de Janela: Um extrapolador que envolve outro extrapolador, limitando o conjunto de parâmetros de verdade fundamental do extrapolador interno para um tamanho de janela fixo

  2. Extrapolador PCA: Um extrapolador que reduz a dimensionalidade dos pontos com a PCA, realiza a extrapolação no espaço pca transformado, e destransforma os resultados antes de retornar.

  3. Extrapolador Sieve: Um extrapolador que executa uma extrapolação, em seguida, agrupa os valores dos parâmetro extrapolados em dois grandes e pequenos clusters, e define os parâmetros dos clusters pequenos como zero.

  4. Extrapolador Polinomial: Um extrapolador baseado em ajustar cada parâmetro a uma função polinomial de um grau especificado pelo usuário.

  5. Extrapolador Diferencial: Um extrapolador baseado no tratamento de cada conjunto de parâmetros como um ponto no espaço, e na realização da regressão para prever o conjunto de parâmetros para o próximo ponto. Um grau especificado pelo usuário também adiciona derivadas aos valores nos vetores dos pontos que servem como features nos dados de treinamento para a regressão linear.

Aqui testamos duas técnicas de extrapolação diferentes

[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

Visualizando os resultados

[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')
../../_images/tutorials_chemistry_05_Sampling_potential_energy_surfaces_23_2.png

Comparando o número de avaliações

[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 SoftwareVersion
Qiskit0.23.6
Terra0.16.4
Aer0.7.5
Ignis0.5.2
Aqua0.8.2
IBM Q Provider0.11.1
System information
Python3.8.6 | packaged by conda-forge | (default, Jan 25 2021, 23:21:18) [GCC 9.3.0]
OSLinux
CPUs8
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.

[ ]: