Electronic Structure Problems with v0.5#
Further resources#
Be sure to check out the following tutorials for how to use the new code:
TL;DR#
This section gives you one cell with a v0.4 code followed by one cell with v0.5 code doing the same things. Hopefully this already gives you all the information which you were looking for.
Previously#
from qiskit_nature.drivers import Molecule
from qiskit_nature.drivers.second_quantization import (
ElectronicStructureDriverType,
ElectronicStructureMoleculeDriver,
PySCFDriver,
)
from qiskit_nature.problems.second_quantization import ElectronicStructureProblem
from qiskit_nature.transformers.second_quantization.electronic import FreezeCoreTransformer
from qiskit_nature.settings import settings
settings.dict_aux_operators = True
molecule = Molecule(
geometry=[["H", [0.0, 0.0, 0.0]], ["H", [0.0, 0.0, 0.735]]], charge=0, multiplicity=1
)
driver = ElectronicStructureMoleculeDriver(
molecule, basis="sto3g", driver_type=ElectronicStructureDriverType.PYSCF
)
# or equivalently:
driver = PySCFDriver.from_molecule(molecule, basis="sto3g")
transformer = FreezeCoreTransformer()
problem = ElectronicStructureProblem(driver, transformers=[transformer])
# Note: at this point, `driver.run()` has NOT been called yet. We can trigger this indirectly like so:
second_q_ops = problem.second_q_ops()
hamiltonian = second_q_ops["ElectronicEnergy"]
print(hamiltonian)
Fermionic Operator
register length=4, number terms=36
-1.2563390730032498 * ( +_0 -_0 )
+ -0.47189600728114245 * ( +_1 -_1 )
+ -1.2563390730032498 * ( +_2 -_2 )
+ -0.47189600728114245 * ( +_3 -_3 )
+ -0.33785507740175813 * ( +_0 +_0 -_0 -_0 )
+ -0. ...
New#
from qiskit_nature.second_q.drivers import PySCFDriver
from qiskit_nature.second_q.formats.molecule_info import MoleculeInfo
from qiskit_nature.second_q.transformers import FreezeCoreTransformer
molecule = MoleculeInfo(["H", "H"], [(0.0, 0.0, 0.0), (0.0, 0.0, 0.735)], charge=0, multiplicity=1)
driver = PySCFDriver.from_molecule(molecule, basis="sto3g")
# this is now done explicitly
problem = driver.run()
transformer = FreezeCoreTransformer()
# and you also apply transformers explicitly
problem = transformer.transform(problem)
hamiltonian = problem.hamiltonian.second_q_op()
print("\n".join(str(hamiltonian).splitlines()[:10] + ["..."]))
Fermionic Operator
number spin orbitals=4, number terms=36
0.33785507740175813 * ( +_0 +_0 -_0 -_0 )
+ 0.09046559989211565 * ( +_0 +_0 -_1 -_1 )
+ 0.09046559989211556 * ( +_0 +_1 -_0 -_1 )
+ 0.33229086512764827 * ( +_0 +_1 -_1 -_0 )
+ 0.33785507740175813 * ( +_0 +_2 -_2 -_0 )
+ 0.09046559989211564 * ( +_0 +_2 -_3 -_1 )
+ 0.09046559989211556 * ( +_0 +_3 -_2 -_1 )
+ 0.33229086512764816 * ( +_0 +_3 -_3 -_0 )
...
qiskit_nature.drivers
#
This section deals exclusively with the migration of the drivers.
The contents of the drivers
submodule has been split into multiple
places. The table below summarizes where each of the components of
qiskit_nature.drivers.second_quantization
has ended up.
Legacy component |
New location |
---|---|
BaseDriver |
|
BasisType |
removed |
ElectronicStructureDriver |
|
ElectronicStructureDriverType |
removed |
ElectronicStructureMoleculeDriver |
removed |
FCIDumpDriver |
|
GaussianDriver |
|
HDF5Driver |
removed |
InitialGuess |
|
MethodType |
|
PSI4Driver |
|
PyQuanteDriver |
removed |
PySCFDriver |
|
Furthermore, the two components from qiskit_nature.drivers
were
moved like so:
Legacy component |
New location |
---|---|
Molecule |
|
UnitsType |
|
A few notes are worth adding:
The driver for pyquante2 was removed, because its source code has not been updated for more than 3 years. Originally, it was supported to enable usage of Qiskit Nature on Windows, however, since then psi4 has also added Windows support and the integration of the Windows Subsystem for Linux has opened up further development possibilities.
The
HDF5Driver
was removed in favor of supporting the standardized QCSchema (seeqiskit_nature.second_q.formats.qcschema
).The
ElectronicStructureMoleculeDriver
was removed because we are steering towards a future with tighter, plugin-like integration with classical codes, making the concept of drivers where Qiskit starts a classical simulation outdated. You can still use the.from_molecule(...)
methods of the remaining drivers in combination with theMoleculeInfo
class.The
MoleculeInfo
has become a pure data container and no longer supports degrees of freedom.The
MoleculeInfo
now separately defines theatoms
andcoords
(coordinates) in favor of the previously combinedgeometry
approach.
Using drivers that were migrated to qiskit_nature.second_q.drivers
#
Previously#
from qiskit_nature.drivers import Molecule
from qiskit_nature.drivers.second_quantization import PySCFDriver
molecule = Molecule(
geometry=[["H", [0.0, 0.0, 0.0]], ["H", [0.0, 0.0, 0.735]]], charge=0, multiplicity=1
)
driver = PySCFDriver.from_molecule(molecule)
result = driver.run()
print(type(result))
<class 'qiskit_nature.properties.second_quantization.electronic.electronic_structure_driver_result.ElectronicStructureDriverResult'>
New#
from qiskit_nature.second_q.drivers import PySCFDriver
from qiskit_nature.second_q.formats.molecule_info import MoleculeInfo
molecule = MoleculeInfo(["H", "H"], [(0.0, 0.0, 0.0), (0.0, 0.0, 0.735)], charge=0, multiplicity=1)
driver = PySCFDriver.from_molecule(molecule, basis="sto3g")
result = driver.run()
print(type(result))
<class 'qiskit_nature.second_q.problems.electronic_structure_problem.ElectronicStructureProblem'>
Notice how the return types differ significantly! For more information
on this be sure to read the section on qiskit_nature.problems
.
Using drivers that were migrated to qiskit_nature.second_q.formats
#
Previously#
from qiskit_nature.drivers.second_quantization import FCIDumpDriver
path_to_fcidump = "aux_files/h2.fcidump"
driver = FCIDumpDriver(path_to_fcidump)
result = driver.run()
print(type(result))
<class 'qiskit_nature.properties.second_quantization.electronic.electronic_structure_driver_result.ElectronicStructureDriverResult'>
New#
from qiskit_nature.second_q.formats.fcidump import FCIDump
path_to_fcidump = "aux_files/h2.fcidump"
fcidump = FCIDump.from_file(path_to_fcidump)
print(type(fcidump))
from qiskit_nature.second_q.formats.fcidump_translator import fcidump_to_problem
problem = fcidump_to_problem(fcidump)
print(type(problem))
<class 'qiskit_nature.second_q.formats.fcidump.fcidump.FCIDump'>
<class 'qiskit_nature.second_q.problems.electronic_structure_problem.ElectronicStructureProblem'>
The reason for distinguishing between drivers
and formats
is
motivated by the fact that the concept of drivers
(in which Qiskit
Nature starts a classical simulation via another program) will become
obsolete when moving towards tighter integration with classical codes
via plugins.
Supporting various formats
and converting them to native objects or
representations of Qiskit Nature, however, is critical to enable fast
adoption and integration with other classical codes. The conceptual
difference is also reflected since loading a problem from a format does
not run another code but merely loads the data from disk.
qiskit_nature.transformers
#
This section deals exclusively with the migration of the transformers.
The table below summarizes where each of the components of
qiskit_nature.transformers
has ended up.
Legacy component |
New location |
---|---|
BaseTransformer |
|
ActiveSpaceTransformer |
|
FreezeCoreTransformer |
|
Transformers still retain their functionality of transforming the result
of a driver into a transformed version of it. However, since the output
type of the drivers
has changed (see above), so has the input and
output type of our transformers
.
Realistically, all you need to do here, is update your import statements, as shown below.
Previously#
from qiskit_nature.drivers.second_quantization import PySCFDriver
from qiskit_nature.transformers.second_quantization.electronic import FreezeCoreTransformer
transformer = FreezeCoreTransformer()
driver = PySCFDriver()
transformed_result = transformer.transform(driver.run())
print(type(transformed_result))
<class 'qiskit_nature.properties.second_quantization.electronic.electronic_structure_driver_result.ElectronicStructureDriverResult'>
New#
from qiskit_nature.second_q.drivers import PySCFDriver
from qiskit_nature.second_q.transformers import FreezeCoreTransformer
transformer = FreezeCoreTransformer()
driver = PySCFDriver()
transformed_result = transformer.transform(driver.run())
print(type(transformed_result))
<class 'qiskit_nature.second_q.problems.electronic_structure_problem.ElectronicStructureProblem'>
The ElectronicStructureProblem
(qiskit_nature.problems
)#
This section details all the changes around the
ElectronicStructureProblem
.
Arguably, the ElectronicStructureProblem
is the class which has
received the most significant changes, because it was the main motivator
for this refactoring. To get started, the table below summarizes the
electronic components of the new qiskit_nature.second_q.problems
module, and shows from where these parts originated in the old code:
New component |
Legacy location |
---|---|
|
|
|
|
|
similar to
|
|
|
|
|
|
did not exist yet |
|
|
Previously#
from qiskit_nature.drivers.second_quantization import PySCFDriver
from qiskit_nature.problems.second_quantization.electronic import ElectronicStructureProblem
from qiskit_nature.transformers.second_quantization.electronic import FreezeCoreTransformer
driver = PySCFDriver()
transformer = FreezeCoreTransformer()
problem = ElectronicStructureProblem(driver, transformers=[transformer])
# we trigger driver.run() implicitly like so:
second_q_ops = problem.second_q_ops()
hamiltonian_op = second_q_ops.pop("ElectronicEnergy")
aux_ops = second_q_ops
New#
from qiskit_nature.second_q.drivers import PySCFDriver
from qiskit_nature.second_q.transformers import FreezeCoreTransformer
driver = PySCFDriver()
problem = driver.run()
transformer = FreezeCoreTransformer()
problem = transformer.transform(problem)
hamiltonian_op, aux_ops = problem.second_q_ops()
For more information on the new and improved
ElectronicStructureProblem
, please refer to the electronic
structure tutorial.
qiskit_nature.properties
#
The properties module has been refactored and split into multiple locations. In this section, we will only be focusing on its electronic components.
The following table lists where each component of
qiskit_nature.properties
has been moved to.
Legacy component |
New location |
---|---|
|
|
|
succeeded by
|
|
removed |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
removed |
|
succeeded by
|
|
removed |
|
removed |
We suggest that you look at the electronic structure tutorial for more in-depth explanations, but we will leave a few comments here:
the
ElectronicBasis
is now only tracked on theElectronicStructureProblem
and not for each operator individuallythe
BasisTransformer
handles basis transformations centrally from thesecond_q.transformers
modulethe new
second_q.properties
components do not store any data which is not needed for operator constructionthe
ElectronicEnergy
(which has always been special) is in the newsecond_q.hamiltonians
module to highlight this special role
If you were previously building custom Property
instances using for
example your own one- and two-body integrals, we suggest that you check
out the documentation of the new
qiskit_nature.second_q.operators.ElectronicIntegrals
. It shows
examples of how to do this in Qiskit Nature v0.5.