Nota

Esta página fue generada a partir de docs/tutorials/05_problem_transformers.ipynb.

Transformación de Problemas#

Este tutorial explica los diversos transformadores de problemas disponibles en Qiskit Nature.

Nota: Actualmente, Qiskit Nature solo tiene transformadores que funcionan con problemas de estructura electrónica.

El BasisTransformer#

Este transformador te permite transformar un ElectronicStructureProblem de una base a otra. Esto es útil en ciertas configuraciones como: - cuando obtuviste una descripción del problema o los coeficientes del Hamiltoniano en la base AO de una fuente externa - cuando generaste explícitamente el problema en la base AO para modificarlo manualmente antes de transformarlo en la base MO - etc.

Dado que podemos lograr el segundo escenario directamente usando Qiskit Nature, eso es lo que haremos aquí. Para obtener más información sobre cómo hacer esto, te recomendamos que leas el tutorial sobre `QCSchema <08_qcschema.ipynb>`__.

Primero, creamos un problema en la base AO para demostrar la transformación de la base:

[1]:
from qiskit_nature.second_q.drivers import PySCFDriver
from qiskit_nature.second_q.problems import ElectronicBasis

driver = PySCFDriver()
driver.run_pyscf()

ao_problem = driver.to_problem(basis=ElectronicBasis.AO)
print(ao_problem.basis)

ao_hamil = ao_problem.hamiltonian
print(ao_hamil.electronic_integrals.alpha)
ElectronicBasis.AO
Polynomial Tensor
 "+-":
[[-1.12421758 -0.9652574 ]
 [-0.9652574  -1.12421758]]
 "++--":
[[[[0.77460594 0.44744572]
   [0.44744572 0.3009177 ]]

  [[0.44744572 0.3009177 ]
   [0.57187698 0.44744572]]]


 [[[0.44744572 0.57187698]
   [0.3009177  0.44744572]]

  [[0.3009177  0.44744572]
   [0.44744572 0.77460594]]]]

A continuación, obtenemos el transformador de AO a MO:

[2]:
from qiskit_nature.second_q.formats.qcschema_translator import get_ao_to_mo_from_qcschema

qcschema = driver.to_qcschema()

basis_transformer = get_ao_to_mo_from_qcschema(qcschema)
print(basis_transformer.initial_basis)
print(basis_transformer.final_basis)
ElectronicBasis.AO
ElectronicBasis.MO

Y finalmente, podemos usar el transformador para obtener el problema en la base MO:

[3]:
mo_problem = basis_transformer.transform(ao_problem)
print(mo_problem.basis)

mo_hamil = mo_problem.hamiltonian
print(mo_hamil.electronic_integrals.alpha)
ElectronicBasis.MO
Polynomial Tensor
 "+-":
[[-1.25633907e+00 -6.21867875e-17]
 [-7.78036432e-17 -4.71896007e-01]]
 "++--":
[[[[6.75710155e-01 1.12401641e-16]
   [1.56722377e-16 1.80931200e-01]]

  [[1.92605510e-16 1.80931200e-01]
   [6.64581730e-01 2.59298923e-16]]]


 [[[8.68926823e-17 6.64581730e-01]
   [1.80931200e-01 1.82411770e-16]]

  [[1.80931200e-01 2.57172666e-16]
   [7.20426423e-17 6.98573723e-01]]]]

Si necesitas construir tu BasisTransformer manualmente, puedes hacerlo así:

[4]:
import numpy as np
from qiskit_nature.second_q.operators import ElectronicIntegrals
from qiskit_nature.second_q.problems import ElectronicBasis
from qiskit_nature.second_q.transformers import BasisTransformer

ao2mo_alpha = np.random.random((2, 2))
ao2mo_beta = np.random.random((2, 2))

basis_transformer = BasisTransformer(
    ElectronicBasis.AO,
    ElectronicBasis.MO,
    ElectronicIntegrals.from_raw_integrals(ao2mo_alpha, h1_b=ao2mo_beta),
)

El FreezeCoreTransformer#

Este transformador te proporciona medios muy simples para congelar los orbitales centrales de tu sistema molecular. Requiere que tu problema contenga el atributo .molecule del cual puede extraer la información atómica necesaria para realizar esta reducción del espacio de Hilbert.

[5]:
from qiskit_nature.second_q.drivers import PySCFDriver

driver = PySCFDriver(atom="Li 0 0 0; H 0 0 1.5")

full_problem = driver.run()
print(full_problem.molecule)
print(full_problem.num_particles)
print(full_problem.num_spatial_orbitals)
Molecule:
        Multiplicity: 1
        Charge: 0
        Unit: Bohr
        Geometry:
                Li      (0.0, 0.0, 0.0)
                H       (0.0, 0.0, 2.8345891868475928)
        Masses:
                Li      7
                H       1
(2, 2)
6

A continuación, aplicamos el FreezeCoreTransformer que en este caso eliminará el orbital de energía más bajo (reduciendo el número total de orbitales espaciales de 6 a 5) y también eliminará los dos electrones dentro de ese orbital (como se refleja en el número cambiado de partículas).

[ ]:

[6]:
from qiskit_nature.second_q.transformers import FreezeCoreTransformer

fc_transformer = FreezeCoreTransformer()

fc_problem = fc_transformer.transform(full_problem)
print(fc_problem.num_particles)
print(fc_problem.num_spatial_orbitals)
(1, 1)
5

Ten en cuenta que esta transformación dará como resultado una compensación de energía constante como resultado de la eliminación de los electrones del núcleo. Este desplazamiento se registra dentro del atributo constants del Hamiltoniano, que puedes inspeccionar como se muestra a continuación:

[7]:
print(fc_problem.hamiltonian.constants)
{'nuclear_repulsion_energy': 1.05835442184, 'FreezeCoreTransformer': -7.840306048789075}

Además, puedes proporcionar una lista de índices orbitales (basados en 0) que se eliminarán del sistema.

Nota: estos orbitales deben estar desocupados, de lo contrario, incurrirás en un gran error en tu cálculo (incluso si están desocupados, debes saber qué orbitales estás eliminando, porque eliminar los incorrectos aún puede generar grandes errores si la dinámica de los sistemas se altera significativamente). No hay guardias para verificar que los índices orbitales provistos estén desocupados, ¡así que depende de ti!

[8]:
fc_transformer = FreezeCoreTransformer(remove_orbitals=[4, 5])

fc_problem = fc_transformer.transform(full_problem)
print(fc_problem.num_particles)
print(fc_problem.num_spatial_orbitals)
(1, 1)
3

El ActiveSpaceTransformer#

Este transformador generaliza la reducción del espacio de Hilbert que realiza el FreezeCoreTransformer. En pocas palabras, te permite especificar un espacio activo seleccionando el número de electrones activos y el número de orbitales espaciales activos. De acuerdo con estos ajustes, el espacio activo se elegirá alrededor del nivel de Fermi.

[9]:
from qiskit_nature.second_q.drivers import PySCFDriver

driver = PySCFDriver(atom="Li 0 0 0; H 0 0 1.5")

full_problem = driver.run()
print(full_problem.num_particles)
print(full_problem.num_spatial_orbitals)
(2, 2)
6
[10]:
from qiskit_nature.second_q.transformers import ActiveSpaceTransformer

as_transformer = ActiveSpaceTransformer(2, 2)

as_problem = as_transformer.transform(full_problem)
print(as_problem.num_particles)
print(as_problem.num_spatial_orbitals)
print(as_problem.hamiltonian.electronic_integrals.alpha)
(1, 1)
2
Polynomial Tensor
 "+-":
[[-0.78784474  0.0469345 ]
 [ 0.0469345  -0.36211748]]
 "++--":
[[[[ 0.49428349 -0.0469345 ]
   [-0.0469345   0.01213863]]

  [[-0.0469345   0.01213863]
   [ 0.22662427  0.00616268]]]


 [[[-0.0469345   0.22662427]
   [ 0.01213863  0.00616268]]

  [[ 0.01213863  0.00616268]
   [ 0.00616268  0.33881567]]]]

El ActiveSpaceTransformer en Qiskit Nature tiene un truco más bajo la manga porque incluso te permite especificar manualmente los índices de los orbitales activos. Esto te permite seleccionar a mano espacios activos que no se encuentran continuamente alrededor del nivel de Fermi.

[11]:
as_transformer = ActiveSpaceTransformer(2, 2, active_orbitals=[0, 4])

as_problem = as_transformer.transform(full_problem)
print(as_problem.num_particles)
print(as_problem.num_spatial_orbitals)
print(as_problem.hamiltonian.electronic_integrals.alpha)
(1, 1)
2
Polynomial Tensor
 "+-":
[[-4.00500243e+00 -7.24056534e-19]
 [-7.24056534e-19 -6.19047188e-01]]
 "++--":
[[[[ 1.65816678e+00  4.90223201e-19]
   [ 4.90223201e-19  9.81922731e-03]]

  [[ 4.90223201e-19  9.81922731e-03]
   [ 3.96308164e-01 -1.10622223e-19]]]


 [[[ 4.90223201e-19  3.96308164e-01]
   [ 9.81922731e-03 -1.10622223e-19]]

  [[ 9.81922731e-03 -1.10622223e-19]
   [-1.10622223e-19  3.12945511e-01]]]]
[12]:
import qiskit.tools.jupyter

%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
qiskit-terra0.23.0.dev0+3ce1737
qiskit-aer0.11.1
qiskit-nature0.5.0
System information
Python version3.9.15
Python compilerGCC 12.2.1 20220819 (Red Hat 12.2.1-2)
Python buildmain, Oct 12 2022 00:00:00
OSLinux
CPUs8
Memory (Gb)62.501182556152344
Sat Nov 05 16:41:31 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.