নোট
This page was generated from docs/tutorials/05_problem_transformers.ipynb.
Transforming Problems#
This tutorial explains the various problem transformers available in Qiskit Nature.
Note: Currently, Qiskit Nature only has transformers which work with electronic structure problems.
The BasisTransformer
#
This transformer allows you to transform an ElectronicStructureProblem
from one basis into another. This is useful in certain settings such as: - when you obtained a problem description or the Hamiltonian coefficients in the AO basis from an external source - when you explicitly generated the problem in the AO basis to modify it manually before transforming into the MO basis - etc.
Since we can achieve the second scenario directly using Qiskit Nature, that is what we will be doing here. To learn more about how to do this, we recommend that you read the tutorial on the `QCSchema
<08_qcschema.ipynb>`__.
First, we create a problem in the AO
basis in order to demonstrate the basis transformation:
[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]]]]
Next, we obtain the AO
to MO
transformer:
[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
And finally, we can use the transformer to obtain the problem in the MO
basis:
[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]]]]
If you need to construct your BasisTransformer
manually, you can do this like so:
[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),
)
The FreezeCoreTransformer
#
This transformer provides you with the very simple means to freeze the core orbitals of your molecular system. It requires your problem to contain the .molecule
attribute from which it can extract the atomic information necessary to perform this Hilbert space reduction.
[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
In the following, we apply the FreezeCoreTransformer
which in this case will remove the single lowest energy orbital (reducing the total number of spatial orbitals from 6 to 5) and also removing the two electrons from within that orbital (as reflected by the changed number of particles).
[ ]:
[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
Note, that this transformation will result in a constant energy offset resulting from the removal of the core electrons. This offset is registered inside of the hamiltonian’s constants
attribute, which you can inspect like shown below:
[7]:
print(fc_problem.hamiltonian.constants)
{'nuclear_repulsion_energy': 1.05835442184, 'FreezeCoreTransformer': -7.840306048789075}
Furthermore, you can provide a list of orbital indices (0-based) which are to be removed from the system.
Note: these orbitals must be unoccupied, otherwise you will incur a large error in your computation (even if they are unoccupied you should know which orbitals you are removing, because removing the wrong ones can still incur large errors if the systems dynamics are altered significantly). No guards are in place to check that the provided orbital indices are indeed unoccupied, so this is up to you!
[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
The ActiveSpaceTransformer
#
This transformer generalizes the Hilbert space reduction which is performed by the FreezeCoreTransformer
. Simply put, it allows you to specify an active space by selecting the number of active electrons and the number of active spatial orbitals. According to these settings, the active space will be chosen around the Fermi level.
[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]]]]
The ActiveSpaceTransformer
in Qiskit Nature has one more trick up its sleeve because it even allows you to manually specify the indices of the active orbitals. This enables you to hand-pick active spaces which do not lie continuously around the Fermi level.
[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 Software | Version |
---|---|
qiskit-terra | 0.23.0.dev0+3ce1737 |
qiskit-aer | 0.11.1 |
qiskit-nature | 0.5.0 |
System information | |
Python version | 3.9.15 |
Python compiler | GCC 12.2.1 20220819 (Red Hat 12.2.1-2) |
Python build | main, Oct 12 2022 00:00:00 |
OS | Linux |
CPUs | 8 |
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.