Release Notes#
0.7.2#
New Features#
The
AngularMomentum.overlap()property will now warn the user, when this matrix is non-unitary.
Added support for using Qiskit Nature with Python 3.12.
Bug Fixes#
Fixes the
AngularMomentumoperator further to also support cases where the number of beta-spin particles exceeds the number of alpha-spin particles.
The commutator methods were faultily trying to call
normal_order()on their operands, which are not guaranteed to have this method. Now, they no longer call this method and instead it is up to the user to normal-order the result as needed.
0.7.1#
New Features#
Added the
get_overlap_ab_from_qcschema()function which extracts the alpha-beta spin orbital overlap matrix from aQCSchemainstance.
Bug Fixes#
Fixes the following operators when dealing with non-orthonormal orbitals (for example when using unrestricted spin orbitals): -
AnglarMomentum-s_plus_operator()-s_minus_operator()-s_x_operator()-s_y_operator()To make the fix take effect, the new additional overlap argument needs to be provided to all of these operators.
Prior to this fix, none of the operators above were able to resolve any spin contamination and would yield misleadingly “clean” expectation values. See this issue for a more complete discussion.
0.7.0#
Prelude#
Qiskit Nature has been migrated to the qiskit-community Github organization to further emphasize that it is a community-driven project. To reflect this change and because we are onboarding additional codeowners and maintainers, with this version (0.7) we have decided to remove all deprecated code, regardless of the time of its deprecation. This ensures that the new members of the development team do not have a large bulk of legacy code to maintain. This can mean one of two things for you as the end-user:
Nothing, if you already migrated your code and no longer rely on any deprecated features.
Otherwise, you need to migrate your code immediately. If you cannot do that, or want to continue using some of the features that were removed, you should pin your version of Qiskit Nature to 0.6
You can check out the migration guides for details on how to update your code. For more context on the changes around Qiskit Nature and the other application projects as well as the algorithms library in Qiskit, be sure to read this blog post.
New Features#
Adds a new lattice class,
HexagonalLatticefor the generation of hexagonal lattices.You construct a hexagonal lattice by specifying the number of rows and columns of hexagons. You can also specify the edge- and on-site-parameters.
Below is a simple example to illustrate this:
from qiskit_nature.second_q.hamiltonians.lattices import HexagonalLattice lattice = HexagonalLattice( 2, 3, edge_parameter=1.0, onsite_parameter=1.5, )
Adds a new lattice class,
KagomeLatticefor the generation of kagome lattices.For example, you can construct a kagome lattice with 4 and 3 unit cells in the x and y direction, respectively, which has weights 1.0 on all edges, weights 1.5 on self-loops and open boundary conditions
from qiskit_nature.second_q.hamiltonians.lattices import ( KagomeLattice, BoundaryCondition, ) kagome = KagomeLattice( 4, 3, edge_parameter = 1.0, onsite_parameter = 1.5, boundary_condition = BoundaryCondition.OPEN )
Adds new operator generator functions to allow more fine-grained spin observables. The new functions are:
the \(S^+\) operator:
s_plus_operator()the \(S^-\) operator:
s_minus_operator()the \(S^x\) operator:
s_x_operator()the \(S^y\) operator:
s_y_operator()the \(S^z\) operator:
s_z_operator()
All of these functions take the number of spatial orbitals as their only argument and return the constructed
FermionicOp.This also allows a much simpler implementation of the
AngularMomentumwhich is simply the $S^2$ operator:\[S^2 = S^- S^+ + S^z (S^z + 1)\]
Introduced a new feature that implements the bosonic operator
BosonicOp. Its functionalities are analogous to theFermioniOp, but for commuting bosonic particles. It should be used to represent a bosonic operator, so if one wants to represent the boson number operator it should do for example:from qiskit_nature.second_q.operators import BosonicOp bosonic_op = BosonicOp({'+_0 -_0': 1}, num_modes=1)
Due to the nature of bosonic particles, this class uses the commutator relations instead of the anti-commutator ones (used by fermionic particles).
In order to use the bosonic operator for quantum applications, this feature also introduces the bosonic linear mapper, which allows to map the BosonicOp to the qubit space. This mapper is based on this paper. To use this mapper one can for example:
from qiskit_nature.second_q.mappers import BosonicLinearMapper mapper = BosonicLinearMapper(truncation=1) qubit_op = mapper.map(bos_op)
The symmetry folding and unfolding routines listed below could become severe bottlenecks for larger system sizes. Now, when PySCF is installed, its routine will be used which is significantly faster.
Adds a new
multiargument to thePolynomialTensor.apply()method which allows handling of numpy routines which return more than one array. The same argument also gets exposed byElectronicIntegrals.apply().
Adds the following new utility methods for splitting and stacking multi-tensors:
Adds the
SparseLabelOp.from_terms()method which is the inverse ofSparseLabelOp.terms().
Adds the
SparseLabelOp.permute_indices()method which allows index permutations to be applied to an operator. For example:from qiskit_nature.second_q.operators import FermionicOp op = FermionicOp({"+_0 +_2 -_1 -_3": 1.0}, num_spin_orbitals=4) permuted_op = op.permute_indices([3, 1, 0, 2]) print(permuted_op) # Fermionic Operator # number spin orbitals=4, number terms=1 # 1.0 * ( +_3 +_0 -_1 -_2 )
This is a very powerful method so caution is advised when using it as other components of the stack may rely on assumptions which are no longer valid after such a permutation (for example the builtin two-qubit reduction of the
ParityMapper).
The
SparseLabelOp.register_lengthattribute (and by extension that of its subclasses, too) can no longer takeNoneas its value. However, the attributes which this one might rely on (e.g.FermionicOp.num_spin_orbitalsorBosonicOp.num_modes) can remainNone. This ensures that the lower-bound behavior works as intended.
Added linear algebra utilities for performing the double-factorization of a two-body tensor:
The
active_orbitalsargument of theActiveSpaceTransformermay now also take a pair of lists of integers, each of which have a length identical to the number of active spatial orbitals. In this case, the first list indicates the alpha- and the second list the beta-spin orbital indices, respectively.
Adds a new convenience subclass of the
UCCansatz. Namely, the spin-symmetry-adapted ansatz,PUCCSD, which includes single and double excitations while always pairing the excitations such that both, the number of particles and the total spin, will be preserved.You can use it like any of the other
UCC-style ansätze, for example:from qiskit_nature.second_q.circuit.library import PUCCSD from qiskit_nature.second_q.mappers import JordanWignerMapper ansatz = PUCCSD( num_spatial_orbitals=4, num_particles=(2, 2), qubit_mapper=JordanWignerMapper(), )
Added the new
include_imaginarykeyword argument to theUCC,UCCSD, andPUCCDclasses. WhenTrue, an extra ansatz parameter is added to each excitation that controls the imaginary contribution to its evolution. Thus, this setting doubles the total number of ansatz parameters, as compared to the default setting ofFalse.
Upgrade Notes#
Support for running with Python 3.7 has been removed. To run Nature you need a minimum Python version of 3.8.
Bug Fixes#
The
ActiveSpaceTransformerwould sometimes set the wrong number of active particles because of a flawed integer rounding. This has now been fixed.
Fixes a formatting issue when printing an
ElectronicStructureResultwhich contains values inextracted_transformer_energies
Fixes the tutorial for the excited state solvers. In doing so, the
EvaluationRuleis properly exposed for importing and documenting accordingly.
Fixes the computation of
ElectronicEnergy.coulomb()(and by extensionElectronicEnergy.fock()) when applied to a purely alpha-spin Hamiltonian but providing a mixed spin density.
Fixes the behavior of the
FreezeCoreTransformerwhen a charge is present on the molecule.
When using
SparseLabelOp.from_polynomial_tensor()constructor for one ofBosonicOp,FermionicOp,SpinOp, orVibrationalOp, the coefficient for the constant term was a 0d Tensor object rather than a number. This has been fixed.
The
ElectronicStructureProblem.reference_energyis now properly propagated to theElectronicStructureResult.hartree_fock_energy.
Fixes the logic of the
InterleavedQubitMapperto actually perform the interleaving on the second-quantization level rather than the qubit level. This ensures that the actually expected benefits from using an interleaved ordering (for example when mapping a paired double-excitation where all Z terms cancel each other) occur, rather than a naive re-shuffling of the already mapped qubit operator.
Fixes the behavior of
SpinOp.to_matrix()for operators acting on more than a single spin.
Fixes the
copy.copyandcopy.deepcopyoperations for theTensorclass.
Fixes a regression in the performance of the
map()method
Compatibility fix to support optional sparse install under Python 3.11.
0.6.0#
Prelude#
Qiskit Nature 0.6 focuses on refactoring of the mappers module. To that extent, the QubitConverter class has been deprecated in favor of using the various subclasses of QubitMapper directly. As a short example, while you were doing something similar to this until now:
solver = GroundStateEigensolver(
QubitConverter(ParityMapper(), two_qubit_reduction=True),
VQE(...),
)
result = solver.solve(problem)
you now simply do the following instead:
solver = GroundStateEigensolver(
ParityMapper(num_particles=problem.num_particles),
VQE(...),
)
result = solver.solve(problem)
Check out the migration guide for the QubitConverter for more details. Besides this major refactoring, a few other changes have been done, so be sure to check out the migration guide from 0.5 to 0.6.
New Features#
Adds a Tapered Qubit Mapper class.
TaperedQubitMapperis to be used as a wrapper of another standardQubitMapperthat can apply symmetry reduction techniques to operators at the end of the mapping.The following example shows how this class can be constructed from a mapper and a symmetry object.
driver = PySCFDriver() electronic_structure_problem = driver.run() h2_op, _ = electronic_structure_problem.second_q_ops() mapper = JordanWignerMapper() z2_sym = Z2Symmetries( symmetries=[Pauli("ZIIZ"), Pauli("ZIZI"), Pauli("ZZII")], sq_paulis=[Pauli("IIIX"), Pauli("IIXI"), Pauli("IXII")], sq_list=[0, 1, 2], tapering_values=[-1, 1, -1], ) tapered_qubit_mapper = TaperedQubitMapper(mapper, z2symmetries=z2_sym) qubit_op = tapered_qubit_mapper.map(h2_op)
Adds the method
get_tapered_mapper()to transform aQubitMapperinstance into aTaperedQubitMapperbased on the properties of the current problem.The following example shows how this method can be used to find the symmetries of a problem and create the associate Tapered Qubit Mapper.
driver = PySCFDriver() electronic_structure_problem = driver.run() h2_op, _ = electronic_structure_problem.second_q_ops() mapper = JordanWignerMapper() tapered_qubit_mapper = electronic_structure_problem.get_tapered_mapper(mapper) qubit_op = tapered_qubit_mapper.map(h2_op)
Updates API for the method
symmetry_sector_locator()to accept the newZ2Symmetriesfromquantum_infoas well as the legacyZ2Symmetriesfrom theopflowmodule.
Added support for running with Python 3.11. At the the time of the release, Psi4 and Sparse didn’t have a python 3.11 version.
Three new methods for creating instances
ElectronicDensityhave been added:constructing an empty (or all-zero) density of a given size:
empty = ElectronicDensity.empty(num_spatial_orbitals=4)
constructing an identity density, meaning that the 1-body matrices are initialized with identity matrices
identity = ElectronicDensity.identity(num_spatial_orbitals=4)
constructing from a provided number of particles. This is a shorter variant of the already existing
from_orbital_occupationmethod for the most common use-case.num_spatial_orbitals = 4 num_particles = (2, 2) two_and_two = ElectronicDensity.from_particle_number(num_spatial_orbitals, num_particles) # for example now the 1-body matrices will be: # [[1, 0, 0, 0], # [0, 1, 0, 0], # [0, 0, 0, 0], # [0, 0, 0, 0]]
All of the methods above take the optional keyword-argument
include_rdm2which determines whether or not the 2-body matrices are computed based on the constructed 1-body matrices. By default, this is set toTrue.
Added the
InterleavedQubitMapperwhich allows wrapping of anotherFermionicMapperto produce qubit operators where the alpha- and beta-spin components are arranged in the qubit register in an interleaved rather than blocked order.from qiskit_nature.second_q.mappers import JordanWignerMapper, InterleavedQubitMapper from qiskit_nature.second_q.operators import FermionicOp blocked_mapper = JordanWignerMapper() interleaved_mapper = InterleavedQubitMapper(blocked_mapper) ferm_op = FermionicOp({"+_0 -_1": 1}, num_spin_orbitals=4) blocked_op = blocked_mapper.map(ferm_op) # SparsePauliOp(['IIXY', 'IIYY', 'IIXX', 'IIYX'], coeffs=[-0.25j, 0.25, 0.25, 0.25j]) print(interleaved_mapper.map(ferm_op)) # SparsePauliOp(['IXIY', 'IYIY', 'IXIX', 'IYIX'], coeffs=[-0.25j, 0.25, 0.25, 0.25j])
The example above extends naturally to work with any scenario in which a
FermionicMappermay be used like the construction of aHartreeFockinitial state orUCCansatz, for example.
Calling the
transform_hamiltonian()is now supported, provided that the active space has been prepared properly.# assuming we have the total Hamiltonian of our system available: total_hamiltonian = ElectronicEnergy(...) # now we want to reduce it to an active space of 2 electrons in 2 orbitals transformer = ActiveSpaceTransformer(2, 2) # assuming that our total system size is 10 electrons in 10 orbitals: transformer.prepare_active_space(10, 10) # after preparation, this now works as intended reduced_hamiltonian = transformer.transform_hamiltonian(total_hamiltonian)
Calling the
transform_hamiltonian()is now supported, provided that the active space has been prepared properly.# assuming we have the total Hamiltonian of our system available: total_hamiltonian = ElectronicEnergy(...) # now we want to apply the freeze-core reduction transformer = FreezeCoreTransformer() # since the FreezeCoreTransformer requires molecular system information, # we need to create that data structure like so: molecule = MoleculeInfo( symbols=["Li", "H"], coords=[(0.0, 0.0, 0.0), (0.0, 0.0, 1.6)], ) # and since the system size depends on the basis set, we need to provide # the total number of spatial orbitals separately: total_num_spatial_orbitals = 11 # e.g. the 6-31g basis # this allows us to prepare the active space correctly like so: transformer.prepare_active_space(molecule, total_num_spatial_orbitals) # after preparation, this now works as intended reduced_hamiltonian = transformer.transform_hamiltonian(total_hamiltonian)
Adds the
symmetric_two_bodymodule. This module provides utilities to exploit the inherent symmetries of chemistry-ordered two-body electronic integrals. You may use these to reduce memory consumption of your code, for example like so:from pyscf import gto from qiskit_nature.second_q.hamiltonians import ElectronicEnergy from qiskit_nature.second_q.operators import ( ElectronicIntegrals, PolynomialTensor, ) from qiskit_nature.second_q.operators.symmetric_two_body import S8Integrals mol = gto.M(atom="H 0 0 0; H 0 0 0.735", basis="631g*") hamiltonian = ElectronicEnergy( ElectronicIntegrals( PolynomialTensor( { "+-": mol.get_hcore(), "++--": S8Integrals(mol.intor("int2e", aosym=8)), }, validate=False, ) ) ) print(hamiltonian.second_q_op())
Since these integral containers are integrated into the stack, you can continue to use existing tools such as the
BasisTransformeror even theActiveSpaceTransformeras if you had stored your integrals in standard arrays.
Adds the
use_symmetry_reduced_integralssetting. When set toTrue, this will cause objects like for example theFCIDump,QCSchema, orPySCFDriverto attempt and leverage thesymmetric_two_bodymodule in order to reduce the memory requirements at runtime.
Adds the new
Tensorclass used internally to consistently deal with n-dimensional tensors throughout the stack. This class also exposes thelabel_templatewhich allows an end-user to influence the translation procedure implemented infrom_polynomial_tensor().
Adds the new
tensor_unwrappingsetting which may be set toFalseto disable the unwrapping of internally createdTensorobjects stored inside of aPolynomialTensor. See alsotensor_unwrappingfor more details.
Adds the new argument
num_particlesto theParityMapperwhich will implement the two qubit reduction without requiring an instance ofQubitConverter.from qiskit_nature.second_q.drivers import PySCFDriver from qiskit_nature.second_q.mappers import ParityMapper driver = PySCFDriver() driver_result = driver.run() fermionic_op, _ = driver_result.second_q_ops() mapper = ParityMapper(num_particles=(1, 1)) qubit_op = mapper.map(fermionic_op)
Extends the
VibrationalIntegralsto fall back to usingnumpyarrays when the optionalsparsedependency is not installed.
Leverage library opt_einsum, if installed, for sparse-einsum support. This library supports einsum summation directly on sparse objects as described in its documentation.
The new keyword argument
register_lengthhas been added to theQubitMapper.map()method. This allows the user to set the length of aSparseLabelOpbefore mapping it (since this length is a lower bound).
Improves the
QEOMcode and implements the calculation of excited state properties and transition amplitudes with QEOM.The new functionalities can be used as follows:
from qiskit.algorithms.optimizers import COBYLA from qiskit.primitives import Estimator from qiskit_nature.units import DistanceUnit from qiskit_nature.second_q.algorithms import VQEUCCFactory, GroundStateEigensolver from qiskit_nature.second_q.algorithms.excited_states_solvers import QEOM from qiskit_nature.second_q.algorithms.excited_states_solvers.qeom import EvaluationRule from qiskit_nature.second_q.circuit.library import UCCSD from qiskit_nature.second_q.drivers import PySCFDriver from qiskit_nature.second_q.mappers import QubitConverter from qiskit_nature.second_q.mappers import JordanWignerMapper optimizer = COBYLA(maxiter=500, disp=False) qubit_converter = QubitConverter( JordanWignerMapper(), z2symmetry_reduction=None, two_qubit_reduction=False ) driver = PySCFDriver( atom="H 0 0 0; H 0 0 1.735", basis="sto3g", charge=0, spin=0, unit=DistanceUnit.ANGSTROM, ) es_problem = driver.run() hamiltonian_op, _ = es_problem.second_q_ops() aux_ops = {"hamiltonian": hamiltonian_op} # Qeom results vqe_solver = VQEUCCFactory(Estimator(), UCCSD(), optimizer) me_gsc = GroundStateEigensolver(qubit_converter, vqe_solver) qeom_solver = QEOM( me_gsc, estimator=Estimator(), excitations="sd", aux_eval_rules=EvaluationRule.ALL ) results_qeom = qeom_solver.solve(es_problem, aux_operators=aux_ops) for n, aux_op_eval in enumerate(results_qeom.aux_operators_evaluated): print(f"Properties of eigen state {n}") for aux_name, aux_result in aux_op_eval.items(): print(f" Expectation value of {aux_name} operator: {aux_result}")
Added public methods
symmetry_reduce_clifford()andconvert_clifford()andfind_taper_op()to allow a step by step tapering of operators.
Changed the behavior of the
qiskit_nature.second_q.algorithms.GroundStateEigensolverto not raise an error when the user specifies a auxiliary operator which name clashes an internally constructed operator’s name. The new behavior is to apply precedence to the user-defined operators over the builtin ones in case of conflicts. A warning will be logged when this case happens.
Added a tolerance parameter
tolto control the eigenvalue threshold in the QEOM calculation.
Adds the new
formatting_precisionattribute to all result objects. This attribute sets the number of decimal places to be used when formatting the result object for printing. It defaults to 12.
Added
qiskit_nature.testingto house testing utilities. Currently it contains some functions for random sampling.
Updated the API to allow
QubitMapperobjects in places whereqiskit_nature.second_q.mappers.QubitConverterwere previously required. This addition advances toward a future deprecation ofQubitConverter. All inputs of typeQubitConverternow supportQubitMapperobjects implementing a transformation from second quantized operators to Pauli operators. Note that the mappers currently do not support qubit reduction techniques.
The method
map()now supports individual operators as well as lists and dictionaries of operators.
Deprecation Notes#
Deprecated all
MinimumEigensolverFactoryandEigensolverFactoryclasses. Instead, users should now build the respectively generated solver instances themselves. How-to guides to detail the involved steps have been added:
Deprecated the
to_matrix()method. The same functionality can be achieved via the qubit-operator after applying theJordanWignerMapper(one only needs to adapt to the different basis state ordering due to the reversed bitstring endianness).import numpy as np from qiskit_nature.second_q.mappers import JordanWignerMapper from qiskit_nature.second_q.operators import FermionicOp from qiskit_nature.settings import settings settings.use_pauli_sum_op = False op = FermionicOp({"+_0": 1, "-_1": 1}) mat = op.to_matrix().todense() jw = JordanWignerMapper().map(op) print(np.allclose(mat, jw.to_matrix(), atol=1e-8)) # prints False for pauli in jw.paulis: pauli.x = pauli.x[::-1] pauli.z = pauli.z[::-1] print(np.allclose(mat, jw.to_matrix(), atol=1e-8)) # prints True
The
QubitConverterclass is deprecated in favor of using theQubitMapperimplementations directly. As a consequence of this, all public properties and function arguments which referred to theQubitConverterby name (e.g.qubit_converter) have been deprecated in favor of properties and function arguments referring toQubitMapper(e.g.qubit_mapper), respectively.
The
symmetry_sector_locator()method has been deprecated without a direct replacement. This utility is no longer needed in the new workflow which usesQubitMapperinstances directly. Qubit tapering can instead now be done using theTaperedQubitMapperwhich can be constructed easily using theget_tapered_mapper()method.
The
match_convertargument of thehartree_fock_bitstring_mapped()method has been deprecated without replacement. This utility is no longer needed in the new workflow which usesQubitMapperinstances directly.
The
VQEClientand its matchingVQERuntimeResultare now deprecated. Instead, users should migrate their code to use the Qiskit Runtime Primitives. A guide on how to use this can be found here.
Deprecates
np.ndarrayas the return type of thehijkl,hijkl_ba, andhijkl_bbattributes. Instead, these will always beSymmetricTwoBodyIntegrals. Instances of the latter can be used asnp.ndarrayso in terms of functionality this should not change anything. However,isinstance(integrals, np.ndarray)will not returnTrueforintegralsof typeSymmetricTwoBodyIntegrals. Additionally, the threeFCIDumpattributes will no longer accept physicist-ordered two-body tensors in the future.
Deprecated the default value (
True) oftensor_unwrappingmeaning that in the future__getitem__()will return objects of typeTensor.
The M, Q, W, V matrix setters and M, Q, W, V matrix standard deviation setters from
QEOMResultwere pending deprecated and remain computable from the H and S matrices.
QubitMapper.allows_two_qubit_reductionhas been deprecated. There is no replacement because it is no longer needed in the new design.
All arguments in the
QubitMapperAPI (and its subclasses) which were previously callednmodeshave been renamed toregister_length.
Bug Fixes#
Fixes
SparseLabelOp.assign_parameters()failing to assign parameters recursively.
The commutator methods
commutator(),anti_commutator(), anddouble_commutator()no longer faultily simplify the returned operator (i.e. the absolute tolerance during simplification is set to zero instead of defaulting toSparseLabelOp.atol).
Fixes a bug when printing the
total_dipole_moment_in_debye
Fixes output of
generate_fermionic_excitations()when called withperserve_spin=Falseand unequal number of alpha and beta particles
Fixes the
qcschema_to_problem()method to takeQCWavefunction.eri_mo_abinto account whenQCWavefunction.eri_mo_bais not available.
Fixes the behavior of
is_zero()when called on a parameterized operator.
Fixes a bug when multiplying a
SparseLabelOpwith numpy numeric types from the left.
Removes wrong sign change from
qiskit_nature.second_q.operators.SpinOp.index_order().
Fixes the
normal_order()method, which in turn corrects the commutation relations of this operator type.
Fixes the
VQEClientto work properly with the latest code.
Added missing Gaussian native libraries from package qiskit_nature.second_q.drivers.gaussiand.gauopen to the wheels file distribution.
Fixes a bug in which
BogoliubovTransformwould sometimes throw an error due to an inability to cast complex numbers to floats.
Fix support of
BackendV2in theVQEClient. Previously, backends instantiated with theIBMProviderfailed since they return backends of typeBackendV2, which were not correctly supported in the VQE client. Backends instantiated with theIBMQprovider continue to work as before.
0.5.0#
Prelude#
Qiskit Nature 0.5 comes with a major redesign of the BaseProblem layer of its stack. Rather than tightly integrating drivers and transformers, problems are now a lot more standalone and are generated by the various drivers (or built out by a user to their custom needs directly). As a short example comparing the previous to the new problem creation:
problem = ElectronicStructureProblem(driver, [transformer])
The new design works as follows:
problem = driver.to_problem(include_dipole=True)
reduced_problem = transformer.transform(problem)
Check out the migration guide for electronic structure calculations for more details.
Furthermore, as a general refactoring strategy the code was migrated from locations qiskit_nature.X.second_quantization to qiskit_nature.X.second_q. However, in doing so some classes/modules were re-categorized, so be sure to check out the detailed migration guide for more details.
New Features#
The
algorithmsmodule now requires the new algorithms introduced in Qiskit Terra 0.22 which in turn rely on the Qiskit Primitives themselves. For more details check out the migration guide for problem solving.
The refactoring of the electronic structure stack has enabled the development of third-party plugins allowing classical codes to call Qiskit Nature instead of relying on the development of
driversin the Qiskit Nature package. One example is the new Qiskit Nature PySCF Plugin which can be used like so:from pyscf import gto, scf, mcscf from qiskit.algorithms.optimizers import SLSQP from qiskit.primitives import Estimator from qiskit_nature.second_q.algorithms import GroundStateEigensolver, VQEUCCFactory from qiskit_nature.second_q.circuit.library import UCCSD from qiskit_nature.second_q.mappers import ParityMapper, QubitConverter from qiskit_nature_pyscf import QiskitSolver mol = gto.M(atom="Li 0 0 0; H 0 0 1.6", basis="sto-3g") h_f = scf.RHF(mol).run() norb, nelec = 2, 2 cas = mcscf.CASCI(h_f, norb, nelec) converter = QubitConverter(ParityMapper(), two_qubit_reduction=True) vqe = VQEUCCFactory(Estimator(), UCCSD(), SLSQP()) algorithm = GroundStateEigensolver(converter, vqe) cas.fcisolver = QiskitSolver(algorithm) cas.run()
Qiskit Nature still provides
driversto enable simple testing and provide a more accessible entry to Qiskit Nature for users who do not come from a classical chemistry computing background. Check out the migration guide for electronic structure calculations to learn how to update your code to use the refactored drivers.
The
propertiesconcept has been largely redesigned and is a lot more refined now. Instead of being a “catchall” for operator factories, the module has been cleanly separated into various components. Check out the corresponding section of the migration guide for electronic structure calculations for more details.
The vibrational structure stack has been refactored in-line with the changes to the electronic structure stack mentioned previously. However, changes to this stack also include corrections to the differentiation of real-space and second-quantized coefficients of the Watson hamiltonian. For more details, check out the migration guide for vibrational structure calculations.
The
latticesand relatedLatticeModelclasses have undergone some API changes, particularly around the location of the utility methods for uniform lattice generation. For more details check out the migration guide for lattice models.
Added the
qiskit_nature.second_q.properties.HeisenbergModelwhich implements the Hamiltonian of the Heisenberg model. This model is used in the study of critical points and phase transitions of magnetic systems. Through the choice of the model constants and the external magnetic field, we can produce many models like: XYZ, XXX, Ising model and others.from qiskit_nature.second_q.hamiltonians import HeisenbergModel from qiskit_nature.second_q.hamiltonians.lattices import LineLattice, BoundaryCondition line_lattice = LineLattice(num_nodes=2, boundary_condition=BoundaryCondition.OPEN) heisenberg_model = HeisenbergModel(lattice=line_lattice) print(heisenberg_model.second_q_ops()) # Output: X_0 X_1 * (-1+0j) + Y_0 Y_1 * (-1+0j) + Z_0 Z_1 * (-1+0j) # These tuples allow us to define a Ising model using the HeisenbergModel J = (0.0, 0.0, -1.0) B = (1.0, 0.0, 0.0) ising_model_hm = HeisenbergModel(lattice = line_lattice, coupling_constants = J, ext_magnetic_field = B) print(ising_model_hm.second_q_ops()) # Output: Z_0 Z_1 * (1+0j) + X_0 * (1+0j) + X_1 * (1+0j)
Adds .SparseLabelOp.equiv for checking approximate equality between two SparseLabelOps.
The performance of the following mappers, when used to map multiple operators of identical size, is significantly improved, by means of caching internal structures used during the mapping procedure:
Adds a new Property for the electronic structure stack to evaluate the 1- and 2-body reduced density matrices. Assuming that you already have an instance of your
qiskit_nature.second_q.problems.ElectronicStructureProblem, you can add theqiskit_nature.second_q.properties.ElectronicDensityto it like so:problem: ElectronicStructureProblem = ... from qiskit_nature.second_q.properties import ElectronicDensity # initialize the density in an orthonormal basis simply based on the # orbital occupation numbers alpha_occupation = [1.0, 1.0, 0.0, 0.0] beta_occupation = [1.0, 1.0, 0.0, 0.0] problem.properties.electronic_density = ElectronicDensity.from_orbital_occupation( alpha_occupation, beta_occupation )
Adds the
PropertiesContainerand its subclasses to simplify the handling ofSparseLabelOpsFactoryinstances inside of problems. This container is aMutableSetand enforces at most a single instance of any Property kind to be stored inside of it This is sufficient for all application purposes of the auxiliary operators (which are generated by these objects).from qiskit_nature.second_q.problems import ElectronicPropertiesContainer from qiskit_nature.second_q.properties import ParticleNumber container = ElectronicPropertiesContainer() container.particle_number = ParticleNumber(10, 10) print(ParticleNumber in container) # True container.particle_number = None print(ParticleNumber in container) # False class MyCustomProperty: # implements the SparseLabelOpsFactory protocol ... custom = MyCustomProperty() container.add(custom) print(custom in container) # True container.discard(MyCustomProperty) print(custom in container) # False
Adds the new keyword argument
mirrorto theSUCCDansatz, which allows the inclusion of symmetrically mirrored double excitations while preserving the number of circuit parameters.from qiskit_nature.second_q.circuit.library.ansatzes import SUCCD from qiskit_nature.second_q.mappers import JordanWignerMapper, QubitConverter converter = QubitConverter(JordanWignerMapper()) ansatz = SUCCD(converter, (1, 1), 6, mirror=True)
Adds support for the QCSchema via which we aim to standardize the I/O between classical drivers and Qiskit Nature.
Implements both
HartreeFockandVSCFas subclasses ofBlueprintCircuit. This allows the respective classes to be instantiated without explicitly setting all of their instance attributes. Missing attributes can be set at a later point to complete the respective circuit definitions.from qiskit_nature.second_q.circuit.library import HartreeFock, VSCF from qiskit_nature.second_q.mappers import JordanWignerMapper, QubitConverter # Initialize Hartree-Fock initial_state without specifying # the number of particles and qubit converter. hf_state = HartreeFock(num_spatial_orbitals=4) # ... # complete circuit definition by specifying the rest of the instance attributes hf_state.qubit_converter = QubitConverter(JordanWignerMapper()) hf_state.num_particles = (1,1) # ... # Similarly for VSCF vscf_state = VSCF() # ... # complete circuit definition by specifying the rest of the instance attributes vscf_state.num_modals = [2, 2] # ...
The new
qiskit_nature.second_q.operators.FermionicOpreplaces the oldqiskit_nature.operators.second_quantization.operators.FermionicOp. This new operator is a subclass of theqiskit_nature.second_q.operators.SparseLabelOpand, as such, only support sparse labels. It is initialized with a dictionary, mapping sparse label keys to coefficients. It supports the usual algebra for operator addition, scalar multiplication, operator composition, operator tensoring, and complex conjugation. It also provides methods for sorting, equality and equivalency checking, operator simplification, normal ordering, and the computation of induced norms as well as hermiticity properties. Finally, it can also be converted to matrices in the occupation number basis.from qiskit_nature.second_q.operators import FermionicOp op1 = FermionicOp({"+_0 -_1": 1.0}, register_length=2) # scalar multiplication op2 = 2.0 * op1 # operator addition op1 + op2 # operator composition op1 @ op2 # operator tensoring op1 ^ op2 # complex conjugation op1.adjoint() # equality and equivalency checks op1 == op2 op1.equiv(op2) # simplification and normal ordering op3 = FermionicOp({"+_0 -_0 +_0 -_0": 1.0}, register_length=2) op3.simplify() op3.normal_ordered() # sorting op4 = FermionicOp({"+_0": 2, "+_2": 1, "+_1": 1}, register_length=3) op4.sort(weight=False) op4.sort(weight=True) # matrix conversion op3.to_matrix(sparse=True) op3.to_matrix(sparse=False) # norm and hermiticity computation op1.induced_norm() op1.is_hermitian()
Added the
xcfargument to theqiskit_nature.second_q.drivers.GaussianForcesDriver.from_molecule()which allows specifying the exchange-correlation functional to be used by Gaussian.
The
excitation_listproperty has been removed fromHFInitialPoint,MP2InitialPoint, andVSCFInitialPoint. Thus the excitation list cannot be set directly, rather this must be set via theansatz.
Following the MP2 T2 and energy correction calculation fix, the APIs for
MP2InitialPointandHFInitialPointhave been changed slightly. After setting thegrouped_property, thetotal_energyandenergy_correctionare now accessed via their respective properties, rather than viaget_energyandget_energy_correction.
Adds atol parameter to
SparseLabelOp.is_hermitian().
The supported
excitationtypes in the QEOM code have been updated. It now exposes the full set of excitation generation functionalities provided by the internally used UCC and UVCC ansatze. In particular, this means that rather than providing a custom list of excitation tuples, a function can be set by the user which generates such a custom list. The documentation has been updated accordingly to reflect this in all places.
Changes usage of library
retworkxto the new substituterustworkx.
Adds utility functions for converting between chemists’ and physicists’ index ordering for two-body integrals.
qiskit_nature.second_q.operators.tensor_ordering.to_chemist_ordering()converts from physicists’ or intermediate order to chemists’, whereasqiskit_nature.second_q.operators.tensor_ordering.to_physicist_ordering()converts to physicists’.qiskit_nature.second_q.operators.tensor_ordering.find_index_order()returns the index-order type for a given two-body tensor.
Deprecation Notes#
The protein folding stack has been migrated to Qiskit Research. Thus, all of its components in Qiskit Nature have been deprecated.
The
BOPESSamplerhas been deprecated without direct replacement. For the future direction in which classical codes will be calling Qiskit Nature (instead of the use ofdrivers) the features provided by the sampler are no longer the responsibility of Qiskit Nature. A warm-startingInitialPointutility has been suggested. You can subscribe to that feature request to receive updates.
Deprecated all code that was migrated to
qiskit_nature/second_qaccording to issue: https://github.com/Qiskit/qiskit-nature/issues/749The following table provides a rough overview of the old and new package locations. In certain cases, single classes might have been treated differently. Be sure to check out the referenced issues or the migration guide for more details.
Old
New
qiskit_nature.algorithms
qiskit_nature.second_q.algorithms
qiskit_nature.algorithms.pes_samplers
Removed. For more details, refer to: https://github.com/Qiskit/qiskit-nature/issues/750
qiskit_nature.circuit
qiskit_nature.second_q.circuit
qiskit_nature.converters
qiskit_nature.second_q.mappers
qiskit_nature.drivers
qiskit_nature.second_q.drivers and qiskit_nature.second_q.formats
qiskit_nature.mappers
qiskit_nature.second_q.mappers
qiskit_nature.operators
qiskit_nature.second_q.operators
qiskit_nature.problems
qiskit_nature.second_q.problems
qiskit_nature.problems.sampling
Moved to qiskit-research. For more details, refer to: https://github.com/qiskit-research/qiskit-research
qiskit_nature.properties
qiskit_nature.second_q.hamiltonians and qiskit_nature.second_q.properties For more details, refer to: https://github.com/Qiskit/qiskit-nature/issues/705
qiskit_nature.results
qiskit_nature.second_q.problems
qiskit_nature.transformers
qiskit_nature.second_q.transformers
The utility methods building out the
QEOMhopping operators have been moved away from theBaseProbleminterface and have been attached to theQEOMimplementation itself.
Bug Fixes#
Fix the initial point classes to account for the number of times the evolved operators are repeated in the ansatz.
Fixes the compatibility of the fermionic excitation generator options which disables spin preserving while also enabling generalized behavior. Now, combining
generalized=Truewithpreserve_spin=Falseresults in all combinations of excitations in the given spin orbital space. De-excitations are not included and filtered accordingly.
Fixes a bug where numpy integer objects were causing integer-based isinstance checks to fail. This also avoids such problems by explicitly converting integer values to Python integers when loading properties from HDF5 files.
Fixed the MP2 T2 amplitudes and energy correction computation to ensure it matches the result from PySCF.
Fixes an issue in the Gaussian Log parsing when the A to H data is provided across multiple instead of on a single line in the file.
Fixes the behavior of
FermionicOp.simplifywhen called on a zero-operator.
Fixes the
qiskit_nature.runtime.VQEClientto correctly detect the type of the wrapped auxiliary operators. Previously, it would always wrap them into a dictionary and then fail when unwrapping them later, since it did not preserve the previously wrapped data type.
The gathering of the auxiliary operator results when using the VQEClient.
Fixes a bug that caused
FermionicOp.is_hermitian()to return false negatives due to not normal-ordering.
Fixes a bug that caused
FermionicOp.simplify()to fail when the simplified operator is equal to zero.
Other Notes#
The classes
VQEProgramandVQEProgramResulthave been removed following the end of the deprecation period.
0.4.0#
New Features#
Adds Hartree-Fock (HF) and vibrational self-consistent field (VSCF) initial point classes.
HFInitialPointandVSCFInitialPoint, are to be used withUCC, andUVCC, respectively.This follows the introduction of
MP2InitialPointfor computing the initial point using the Møller-Plesset 2nd Order (MP2) corrections.MP2InitialPoint,HFInitialPoint, andVSCFInitialPointall inherit from the abstract base classInitialPoint.These initial points are intended to be used as starting VQE parameters when using a UCC ansatz (cluster operator coefficients). This should introduce an initial point that is closer to the ground state point, leading to fewer overall evaluations for VQE.
Instances of the appropriate classes are now the default
initial_pointarguments inVQEUCCFactoryandVQEUVCCFactory. Additionally, one may pass an explicitInitialPointinstance to the factories. Following are some example snippets.VQE UCC with a HFInitialPoint:
hf_intial_point = HFInitialPoint() vqe_ucc_factory = VQEUCCFactory(quantum_instance, initial_point=hf_initial_point)
VQE UCC with an MP2InitialPoint:
mp2_intial_point = MP2InitialPoint() vqe_ucc_factory = VQEUCCFactory(your_quantum_instance, initial_point=mp2_initial_point)
VQE UVCC with a VSCFInitialPoint:
vscf_intial_point = VSCFInitialPoint() vqe_uvcc_factory = VQEUVCCFactory(your_quantum_instance, initial_point=vscf_initial_point)
They can also be used by following the snippets below and passing the result via
initial_pointto the VQE.UCC with a HF initial point:
hf_intial_point = HFInitialPoint() hf_initial_point.ansatz = your_ucc_ansatz initial_point = hf_initial_point.to_numpy_array()
UVCC with a VSCF initial point:
vscf_initial_point = VSCFInitialPoint() vscf_initial_point.ansatz = your_uvcc_ansatz initial_point = vscf_initial_point.to_numpy_array()
Added logging utility functions accessible through qiskit_nature.logging.
Added Support for Bohr unit in Molecule Class:
mol = Molecule(geometry=[("H", [10.0, 2.0, 0.0]), ("H", [0.0, 20.0, 1.0])], unit=UnitsType.BOHR)
Adds
BogoliubovTransform. This class constructs a circuit that performs a Bogoliubov transform, which is a single-particle basis change that may or may not conserve particle number. See the Quadratic Hamiltonians and Slater determinants tutorial for a demonstration of how to use this class.
The new setting qiskit_nature.settings.optimize_einsum was added which allows enabling the optimize argument in numpy.einsum calls with more than 2 operands. This is known to yield significant computational efficiency increases at the expense of higher memory consumption. The setting defaults to True.
Adds
qiskit_nature.operators.second_quantization.FermionicOp.terms(). This returns an iterable of (term, coefficient) pairs describing the terms contained in the operator. Each term is a list of tuples of the form (action, index), where the action is either “+” or “-” and the index is the integer index of the factor in the term.
Added Qiskit Terra’s Gradient Functionality to calculate gradients in
AdaptVQE. You can choose the gradient method and input it while callingAdaptVQE. for example:from qiskit.providers.basicaer import BasicAer from qiskit.utils import QuantumInstance from qiskit.opflow.gradients import Gradient from qiskit_nature.algorithms import VQEUCCFactory from qiskit_nature.drivers import UnitsType from qiskit_nature.drivers.second_quantization import PySCFDriver from qiskit_nature.mappers.second_quantization import ParityMapper from qiskit_nature.converters.second_quantization import QubitConverter from qiskit_nature.problems.second_quantization import ElectronicStructureProblem from qiskit_nature.algorithms.ground_state_solvers.adapt_vqe import AdaptVQE driver = PySCFDriver( atom="H .0 .0 .0; H .0 .0 0.735", unit=UnitsType.ANGSTROM, basis="sto3g" ) problem = ElectronicStructureProblem(driver) qubit_converter = QubitConverter(ParityMapper()) solver = VQEUCCFactory(QuantumInstance(BasicAer.get_backend("statevector_simulator"))) grad = Gradient(grad_method="lin_comb", epsilon=1.0) calc = AdaptVQE(qubit_converter, solver, gradient=grad) res = calc.solve(problem)
The HDF5Driver has been refactored to leverage the new HDF5-integration protocol of Qiskit Nature. The driver still supports loading legacy QMolecule HDF5 files and also provides a conversion utility:
driver = HDF5Driver("path_to_qmolecule.hdf5") driver.convert(replace=True)
Adds a new HDF5-integration to support storing and loading of (mostly) Property objects using HDF5 files. A similar feature existed in the legacy QMolecule object but the new implementation is handled more general to enable leveraging this integration throughout more parts of the stack in the future.
To store a driver result of the new drivers in a file you can do:
from qiskit_nature.hdf5 import save_to_hdf5 my_driver_result = driver.run() save_to_hdf5(my_driver_result, "my_driver_result.hdf5")
and to load it again you would do:
from qiskit_nature.hdf5 import load_from_hdf5 my_driver_result = load_from_hdf5("my_driver_result.hdf5")
Support the initialization of FermionicOp with tuple as label.
FermionicOpcan be initialized using a tuple of integers, (action, index), like below:from qiskit_nature.operators.second_quantization import FermionicOp FermionicOp( [([("-", 2), ("+", 1)], 2 + 0j), ([("-", 3)], 34 + 0j)], register_length=4, display_format="sparse", )
Add the option to initialize a
Latticefrom anetworkx.Graphobject, which will be internally converted to aretworkx.PyGraphfor performance.For example, you can now construct a lattice as
import networkx as nx from qiskit_nature.problems.second_quantization.lattice import Lattice # 3-regular random graph on 6 nodes graph = nx.generators.random_graphs.random_regular_graph(3, n=6) lattice = Lattice(graph)
Adds a new problem class,
qiskit_nature.problems.second_quantization.lattice.LatticeModelProblem, for lattice models. It can create second quantized operators from a lattice model. We can use the Ground State Eigensolver with it to calculate the ground state energy.from qiskit_nature.problems.second_quantization.lattice import ( BoundaryCondition, FermiHubbardModel, LineLattice, LatticeModelProblem ) from qiskit.algorithms import NumPyMinimumEigensolver from qiskit_nature.algorithms import GroundStateEigensolver from qiskit_nature.converters.second_quantization import QubitConverter from qiskit_nature.mappers.second_quantization import JordanWignerMapper solver = NumPyMinimumEigensolver() qubit_converter = QubitConverter(JordanWignerMapper()) calc = GroundStateEigensolver(qubit_converter, solver) line_lattice = LineLattice(num_nodes=4, boundary_condition=BoundaryCondition.OPEN) fhm = FermiHubbardModel.uniform_parameters( lattice=line_lattice, uniform_interaction=-1.0, uniform_onsite_potential=0.0, onsite_interaction=5.0, ) lmp = LatticeModelProblem(lattice_model=fhm) res = calc.solve(lmp)
Adds
qiskit_nature.mappers.second_quantization.LogarithmicMapper. This class is a mapper for Logarithmic spin-to-qubit mapping. In this local encoding transformation, each individual spin S system is represented via the lowest lying 2S+1 states in a qubit system with the minimal number of qubits needed to represent >= 2S+1 distinct states.
Adds a class to compute the Møller-Plesset 2nd Order (MP2) corrections. The corresponding double-excitation coefficients are intended to be used as an initial point for the VQE parameters (cluster operator coefficients) when using a UCC ansatz. This should introduce an initial point that is closer to the ground state point, leading to fewer overall evaluations for VQE.
MP2InitialPointinherits from the abstract base class (interface)InitialPoint, which takes a driver result and a UCC ansatz either directly via thecomputemethod or via their respective property setters.The MP2 computation requires the grouped_property to contain the ElectronicEnergy, which must contain the two-body molecular orbital matrix and the orbital energies. Optionally, it will also use the Hartree-Fock reference energy to compute the absolute energy.
When using
VQEUCCFactory, anMP2InitialPointobject can be passed via theinitial_pointkeyword argument:mp2_initial_point = MP2InitialPoint() vqe_ucc_factory = VQEUCCFactory(quantum_instance, initial_point=mp2_initial_point)
In this case the driver result and ansatz will be used to compute the initial point automatically. This will then be passed to the VQE.
Outside of the factory, one can do this manually:
mp2_initial_point = MP2InitialPoint() mp2_initial_point.compute(driver_result, ansatz) initial_point = mp2_initial_point.to_numpy_array() algorithm = VQE( ansatz, optimizer=optimizer, quantum_instance=quantum_instance, initial_point=initial_point )
The eventual intention is to retire
preferred_init_pointsfromVQEin Terra, so the implementation avoids this property.
Improves the performance of the
qiskit_nature.properties.second_quantization.electronic.integrals.ElectronicIntegrals.to_second_q_op()method significantly. Previously, generating the second quantized operators for a system size greater than 20 spin orbitals took on the order of minutes to hours (depending on the actual size). Now, even system sizes of 50 spin orbitals can be handled in a matter of seconds.
Now there is a function to interpret the raw result of solving a protein folding problem. Previously the problem was encoded in order to be solved more efficiently but the result could not be easily understood by a user. This new functionality decodes the result for the user and provides a plotting of the protein as well as a file with the x,y,z coordinates of each one of the beads in the protein.
Added:
ProteinFoldingResult. This class handles the result found by running a VQE to solve aProteinFoldingProblem. This class has:Method
get_figure()which generates a figure of the shape of the protein.Method
save_xyz_file()which saves a .xyz file with the cartesian coordinates of the shape of the molecule.Property
protein_shape_file_genwhich is an instance ofProteinShapeFileGen. This class has in its turn a methodget_xyz_data()which returns an array with the data contained in the .xyz file without having to generate such a file.Property
protein_shape_decoderwhich is an instance ofProteinShapeDecoder. This class has in its turn two propertiesmain_turnsandside_turnsthat return the turn sequences of the main chain and the side chains respectively.
result = protein_folding_problem.interpret(raw_result) # Save xyz file in current directory. result.save_xyz_file() # Generate plot. figure = result.get_figure()
Adds
qiskit_nature.operators.second_quantization.QuadraticHamiltonian. This class is used to represent quadratic fermionic Hamiltonians and includes methods to efficiently diagonalize them.
Adds the simplify method to
qiskit_nature.operators.second_quantization.SecondQuantizedOpand the normal_ordered method toqiskit_nature.operators.second_quantization.FermionicOp. These methods replace reduce and to_normal_order, which are deprecated. The differences between the new and old methods are the following:simplify does not perform normal-ordering, while reduce does
normal_ordered simplifies the result, while to_normal_order does not
Adds functionality to prepare Slater determinants and fermionic Gaussian states using the Givens rotation strategy. This functionality is accessed via the following classes:
qiskit_nature.circuit.library.SlaterDeterminantqiskit_nature.circuit.library.FermionicGaussianState
The solver of
BOPESSamplernow accepts solvers of type Union[GroundStateSolver,ExcitedStatesSolver] instead of only a GroundStateSolver. This generalizes to excited states the sampling of nuclear coordinates for Born Oppenheimer Potential Energy Surfaces. Adds the get_qubit_operators() inqiskit_nature.algorithms.ExcitedStatesEigensolver. This matches the format ofqiskit_nature.algorithms.GroundStateEigensolver. BOPESSampler now also accepts auxiliary operators to pass to the solver. Geometry-dependent observable can also be defined as auxiliaries. See the Sampling the potential energy surface tutorial for a demonstration of how to use this calculation of excited state Born Oppenheimer potential energy surfaces.
VQEClientnow extends VariationalAlgorithm, meaning users can now implementBOPESSamplerusing bootstrapping, which works similarly now with VQEClientVQEClientas it did previously with local VQE.
Upgrade Notes#
Added support for running with Python 3.10. At the the time of the release, PySCF didn’t have a python 3.10 version.
Support for running with Python 3.6 has been removed. To run Nature you need a minimum Python version of 3.7.
Changes the default
display_formatof the constructor ofFermionicOpfrom “dense” to “sparse”.
Deprecation Notes#
The
deltaargument ofAdaptVQEis deprecated in favor of supplying agradientfrom Qiskit Terra’sqiskit.opflow.gradientsframework. In doing so, the default behavior ofAdaptVQEchanges from using a finite difference scheme for the gradient evaluation to using a parameter shift method. In order to reproduce the original default behavior you must specifydelta=1explicitly or use the following:from qiskit.providers.basicaer import BasicAer from qiskit.utils import QuantumInstance from qiskit.opflow.gradients import Gradient from qiskit_nature.algorithms import VQEUCCFactory from qiskit_nature.drivers import UnitsType from qiskit_nature.drivers.second_quantization import PySCFDriver from qiskit_nature.mappers.second_quantization import ParityMapper from qiskit_nature.converters.second_quantization import QubitConverter from qiskit_nature.problems.second_quantization import ElectronicStructureProblem from qiskit_nature.algorithms.ground_state_solvers.adapt_vqe import AdaptVQE driver = PySCFDriver( atom="H .0 .0 .0; H .0 .0 0.735", unit=UnitsType.ANGSTROM, basis="sto3g" ) problem = ElectronicStructureProblem(driver) qubit_converter = QubitConverter(ParityMapper()) solver = VQEUCCFactory(QuantumInstance(BasicAer.get_backend("statevector_simulator"))) grad = Gradient(grad_method="fin_diff", epsilon=1.0) calc = AdaptVQE(qubit_converter, solver, gradient=grad) res = calc.solve(problem)
The following second quantization operator methods are deprecated:
qiskit_nature.operators.second_quantization.SecondQuantizedOp.reduce(). Instead, useqiskit_nature.operators.second_quantization.SecondQuantizedOp.simplify().qiskit_nature.operators.second_quantization.FermionicOp.to_normal_order(). Instead, useqiskit_nature.operators.second_quantization.FermionicOp.normal_ordered().
The argument gss of the constructor of
BOPESSamplerwas deprecated and replaced by state_solver to match the extension of this class toqiskit_nature.algorithms.ExcitedStatesEigensolver. Now the constructor has the following positional argument:state_solver
VQEUCCFactoryhad setter/getter properties that were repeated with respect toqiskit.algorithms.VQE.In order to avoid duplicating all of these attributes, potentially leading to inconsistencies between the attributes of the different classes, these are now deprecated and require you to use the attributes from
minimum_eigensolverinstead.For this reason, the constructor of
VQEUCCFactoryhas been changed as well. Now the constructor only has the following positional arguments:initial_point
initial_state
ansatz
Any extra keyword arguments are passed to a constructor of
qiskit.algorithms.VQEwhich will create a VQE that can be accessed viaminimum_eigensolver.The same changes have been done for
VQEUVCCFactoryandNumPyMinimumEigensolverFactory
Bug Fixes#
The
BOPESSamplerdid not support GroundStateSolvers when built out with MinimumEigensolverFactories. This is fixed, so code like the following now functions correctly:solver = GroundStateEigensolver(converter, VQEUCCFactory(quantum_instance)) sampler = BOPESSampler(solver, bootstrap=True, num_bootstrap=None, extrapolator=None)
Fix incorrect corner cases in BravyiKitaevSuperFastMapper: Input terms with coefficient zero and output operator equal to zero. Also detect and raise an exception if HartreeFock attempts to use the BKSF mapper.
Fix bug in Bravyi-Kitaev Super-Fast (BKSF) Mapper cause by using obsolete method for composing Pauli operators in one kind of fermionic Hamiltonian term.
Fixes a bug in VQEClient using dict based aux_operators instead of deprecated list based ones (enabled via qiskit_nature.settings.dict_aux_operators = True).
Some minor issues in the
ActiveSpaceTransformerwere fixed. Namely:iterated properties are no longer deep-copied resulting in non-transformed ones actually being dropped rather than carried on
the correct return type object is being constructed and returned
Fixes the ability to disable the freeze_core argument of the
FreezeCoreTransformer
Fixes the wrong inference of register_length in
FermionicOp.
Fixes the units used for the Molecule generated by the PySCFDriver.
Fixes the computation of the spin orbital occupation in a non-singlet state. Previously, a singly occupied MO would result in SO occupations of 0.5 for each spin. Now, the alpha SO will be fully occupied and the beta SO unoccupied.
UCCandUVCCwhen fully configured via the constructor failed to transpile and were not valid circuits. This fixes that to ensure that if UCC / UVCC are fully configured then as circuits they are are immediately valid from the get go.
Fix the groundenergy in
EigenstateResultto return a correct value.
Alter
UCCto build theoperatorson demand when requested via the property, rather than, as before, when the circuit is built. Now if the circuit is built, then the operators, if not built, will be created as before, but since they are cached when built, if done earlier, then these are used. This avoids problems when used in conjunction with VQE that presently fail - most cases today use a fully configured UCC being passed into VQE but whose constructor presently has an unintended side-effect of building the circuit via a logging statement. For other scenarios VQE would fail when it checked on number of qubits and the operators were None, even though UCC was fully configured, when the circuit had not yet been built.
Add a type check for the input graphs to
Latticewhich asserts that the edge weights of the graph are either numeric (or one of None or {} which is replaced by a unit weight). This prevents possibly unexpected errors in the application stack when an operator is constructed from the lattice.In particular, the following now raises a ValueError:
from retworkx import PyGraph from qiskit_nature.problems.second_quantization.lattice import Lattice graph = PyGraph(multigraph=False) graph.add_nodes_from(range(3)) graph.add_edges_from([(0, 1, 1), (1, 2, "banana")]) # banana is not a valid weight! lattice = Lattice(graph)
Alter
UVCCto build theoperatorson demand when requested via the property, rather than, as before, when the circuit is built. This is a similar change as was done toUCC.
Ensures the VibrationalStructureProblem.truncation_order gets propagated correctly down to the properties before the SecondQuantizedOp instances are constructed.
0.3.0#
New Features#
The degree_of_freedom attribute of the
Moleculeclass now has its dedicated getter and setter.
Add:
qiskit_nature.problems.second_quantization.lattice.models.IsingModelimplementing the Hamiltonian of the Ising Model. Add:qiskit_nature.problems.second_quantization.lattice.models.LatticeModelimplementing a base class for Lattice models.
Add:
qiskit_nature.problems.second_quantization.lattice.lattice.Latticefor the generation of general lattices.Add:
qiskit_nature.problems.second_quantization.lattice.lattice.HyperCubicLatticefor the generation of arbitrary d-dimensional lattices.Add:
qiskit_nature.problems.second_quantization.lattice.lattice.LineLatticefor the generation of one-dimensional lattices.Add:
qiskit_nature.problems.second_quantization.lattice.lattice.SquareLatticefor the generation of two-dimensional lattices.Add:
qiskit_nature.problems.second_quantization.lattice.lattice.TriangularLatticefor the generation of two-dimensional lattices with diagonal edges.Add:
qiskit_nature.problems.second_quantization.lattice.models.FermiHubbardModelimplementing the Hamiltonian of the Fermi-Hubbard Model.
Exposes the callback option of the VQE algorithm in the VQE factory classes. It also adds a general kwargs dictionary which allows passing any additional arguments to the VQE.
Add
to_matrix(). This method returns the matrix representation of the operator over the full fermionic Fock space in the occupation number basis.
Added Gaussian drivers to allow execution on python 3.9 (MacOS, Windows, Linux).
Support was added for generalized fermionic excitations. These kinds of excitations are effectively ignoring the orbital occupancies and instead yield all possible excitations within a spin species. Furthermore, another option was added which can be used to enabled spin- flipped excitations.
Runs checks for the excitations in a UCC ansatz when the excitations were created by a function. If the excitations are not in the expected format the checks raise a
qiskit_nature.QiskitNatureError.
Upgrade Notes#
In order to fix the
ElectronicStructureProblemsymmetry_sector_locator()information on the mapping was required and theQubitConvertersector_locatorparameter callback signature of theconvert()method was changed fromsector_locator: Optional[Callable[[Z2Symmetries], Optional[List[int]]]]tosector_locator: Optional[Callable[[Z2Symmetries, "QubitConverter"], Optional[List[int]]]]i.e. your supplied callback method must now take a second parameter which is aQubitConverterinstance and when invoked will be the instance upon which theconvertwas called. If you have created your own sector locator then you will need to update it`s signature otherwise the code will fail when calling it now.
The EvolvedOperatorAnsatz, from the Nature circuit.library, which was migrated in an earlier release to core Qiskit i.e. Terra, has now been removed. You should change any code that still uses this over to the core Qiskit one, from qiskit.circuit.library, as a direct replacement.
Deprecation Notes#
Rename the runtime “program” to runtime “client” to avoid name confusions and reflect the fact that it is an interface for code executed in the cloud. The classes
VQEProgramandVQEProgramResulthave been renamed toVQEClient,VQERuntimeResult, respectively.
Bug Fixes#
This also ensures that the getter/setter methods of the VQE factories actually affect the constructed VQE instance.
Fixed the manual active orbital selection when specifying the active number of electrons as a tuple rather than an integer.
Fixed a typo in the ElectronicEnergy._orbital_energies variable name and ensures the correct behavior of the orbital_energies property getter.
The ElectronicStructureResult did not initialize the _computed_dipole_moment variable causing critical errors when trying to print a result from an algorithm which does not compute these observables. Proper initialization fixes this issue. Printing the result would also fail when complex numbers were stored. This has also been remedied.
Fixed an issue where the existing Mapper was incorrectly mapping the creation operator \(+\) and the annihilation operator \(-\). It used to be that \(+\) was mapped to \(\sigma_+\) and \(-\) was mapped to \(\sigma_-\), but it is correct that \(+\) is mapped to \(\sigma_-\) and \(-\) is mapped to :math`sigma_+`.
Fixes the creation on the
HartreeFockinitial state which could fail when Z2Symettry reduction was being used via the providedQubitConverter.Also fixes the
ElectronicStructureProblemsymmetry_sector_locator(), which uses the HartreeFock class too, so that it correctly determines the sector containing the ground state whenautosymmetry reduction is used.
Ensure BaseProblem.molecule_data_transformed is set when using a legacy driver type without any transformers.
Fixes the formatting of the occupied modals and adds the excited state energies when printing a
VibrationalStructureResult.Fixes the return type of
num_occupied_modals_per_mode()fromOptional[List[float]]toOptional[List[List[float]]]
Fixes QEOM such that when using parity mapping with two_qubit_reduction, or Z2 symmetries with any mapping, that the excited states are computed as expected.
Fix the electronic structure problem sector locator such that the ‘auto’ Z2 symmetry conversion, of the qubit converter, results in the ground state for such problems and not some other value due to incorrect sector selection.
Allow input operator to BravyiKitaevSuperFastMapper to be FermionicOp in sparse storage format. Previously, all input was interpreted as dense storage format, which raised an error when parsing sparse format as dense failed.
Updates the runtime tutorial to consistently use the new drivers in combination with the new transformers and the Property-framework in general.
0.2.0#
New Features#
Add
qiskit_nature.mappers.second_quantization.BravyiKitaevSuperFastMapperimplementing the Bravyi-Kitaev super-fast fermion-to-qubit mapping. For examplefrom qiskit_nature.mappers.second_quantization import BravyiKitaevSuperFastMapper mapper = BravyiKitaevSuperFastMapper() mapper.map(fermionic_op)
The
SecondQuantizedOpnow has a methodis_hermitian()method which will returnTrueif the operator is equivalent to its adjoint andFalseotherwise
to_list()is now an abstract method ofSecondQuantizedOpthat is implemented by all subclasses
Add
to_normal_order(). It returns the normal ordered fermionic operator that is equivalent to self.
Introduces the
ElectronicStructureMoleculeDriverandVibrationalStructureMoleculeDriverthat allow for the creation of Molecule-based drivers by specifying a molecule plus basis and method (for Electronic Structure drivers only) and a driver type. An additional type AUTO allows for the lookup of the first driver installed that supports the given method. The documentation of those two molecule driver classes gives more details on it.
The Property framework is the new modular and extensible approach for representing observable quantities. The framework is used as a replacement for the legacy driver results like QMolecule and WatsonHamiltonian. Please refer to the tutorial and documentation for more details. Related Github issues: * https://github.com/Qiskit/qiskit-nature/issues/148 * https://github.com/Qiskit/qiskit-nature/issues/167 * https://github.com/Qiskit/qiskit-nature/pull/220 * https://github.com/Qiskit/qiskit-nature/issues/243 * https://github.com/Qiskit/qiskit-nature/pull/263 * https://github.com/Qiskit/qiskit-nature/issues/264 * https://github.com/Qiskit/qiskit-nature/pull/303
Introduce the
VQEProgramto allow leveraging Qiskit Runtime to speed up the VQE algorithm. TheVQEProgramimplements theMinimumEigensolverinterface and can thus be used as a drop-in replacement for other minimum eigensolvers likeqiskit.algorithms.VQE. See the tutorials under docs/tutorials for an explicit example usage.
Upgrade Notes#
The internal data in
FermionicOphave been changed. As a result, more data type is now accepted by initialize. The ascending order constraint and the no-same index constraint have been removed. In addition, the dense and sparse labels are now automatically detected by the existence of underscores.The property display_format of
FermionicOpis added. There are two modes dense and sparse. This display format can be switched by the property FermionicOp.display_format.
The internal API of the abstract class
qiskit_nature.operators.second_quantization.SecondQuantizedOpabstract class has been changed to useStarAlgebraMixin.
Deprecation Notes#
The
EvolvedOperatorAnsatzis deprecated. UseEvolvedOperatorAnsatzas a direct replacement instead.
The property dagger in the second quantized operators is deprecated. Use adjoint() method alternatively.
the legacy driver return types, QMolecule and WatsonHamiltonian
the legacy transformers acting on the now deprecated driver return types
the BaseProblem.molecule_data and BaseProblem.molecule_data_transformed attributes
All currently existing drivers have been moved from qiskit_nature.drivers to qiskit_nature.drivers.second_quantization. This is necessary because future additions to Nature which reside in parallel to the second_quantization submodules will not be using these drivers. Making this separation reflects that in the code structure. The same change was necessary for the existing qiskit_nature.transformers.
Bug Fixes#
Fixed an issue where
FermionicOpraises unwanted ValueError when initialized with some list of sparse label.
Fixes the issue #198 where total dipole moment was not calculated correctly in the ElectronicStructureResult.
QiskitNatureError``s where not being raised properly by the ``ActiveSpaceTransformerdue to ill-formatted error messages.
Fix
AdaptVQEafter the update ofVQEwhich deleted the internal_energy_evaluationmethod that Adapt-VQE was relying on.
The FreezeCoreTransformer (and ActiveSpaceTransformer) were incompatible with the automatic Z2Symmetry reduction. This issue was fixed by correcting the ElectronicStructureProblem.symmetry_sector_locator method.
The two-qubit reduction needs to be skipped when a qubit operator only has 2 (or even fewer) qubits.
The
VQEProgramdoes support the evaluation of auxiliary operators at the final state, but theqiskit_nature.runtime.VQEProgram.supports_aux_operators()method previously returned False instead of True.
Allow Qiskit’s
Optimizerclasses as input for theoptimizerin theVQEPrograminstead of only dictionaries.
Other Notes#
Changed documentation and code to better reflect rebranding of Qiskit’s chemistry module as Qiskit Nature.