Skip to content

Qiskit Nature 0.7.0

Compare
Choose a tag to compare
@mrossinek mrossinek released this 09 Nov 17:14
· 35 commits to main since this release
ed6d0c1

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:

  1. Nothing, if you already migrated your code and no longer rely on any deprecated features.

  2. 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, HexagonalLattice for 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, KagomeLattice for 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 AngularMomentum which 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 the FermioniOp, 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.

    • unfold_s4_to_s1()
    • unfold_s8_to_s1()
    • unfold_s8_to_s4()
    • fold_s1_to_s4()
    • fold_s1_to_s8()
    • fold_s4_to_s8()
  • Adds a new multi argument to the PolynomialTensor.apply() method which allows handling of numpy routines which return more than one array. The same argument also gets exposed by ElectronicIntegrals.apply().

  • Adds the following new utility methods for splitting and stacking multi-tensors:

    • PolynomialTensor.split()
    • PolynomialTensor.stack()
    • ElectronicIntegrals.split()
    • ElectronicIntegrals.stack()
  • Adds the SparseLabelOp.from_terms() method which is the inverse of SparseLabelOp.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_length attribute (and by extension that of its subclasses, too) can no longer take None as its value. However, the attributes which this one might rely on (e.g. FermionicOp.num_spin_orbitals or BosonicOp.num_modes) can remain None. This ensures that the lower-bound behavior works as intended.

  • Added linear algebra utilities for performing the double-factorization of a two-body tensor:

    • qiskit_nature.utils.double_factorized()
    • qiskit_nature.utils.modified_cholesky()
  • The active_orbitals argument of the ActiveSpaceTransformer may 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 UCC ansatz. 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_imaginary keyword argument to the UCC, UCCSD, and PUCCD classes. When True, 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 of False.

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 ActiveSpaceTransformer would 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 ElectronicStructureResult which contains values in extracted_transformer_energies
  • Fixes the tutorial for the excited state solvers. In doing so, the EvaluationRule is properly exposed for importing and documenting accordingly.
  • Fixes the computation of ElectronicEnergy.coulomb() (and by extension ElectronicEnergy.fock()) when applied to a purely alpha-spin Hamiltonian but providing a mixed spin density.
  • Fixes the behavior of the FreezeCoreTransformer when a charge is present on the molecule.
  • When using SparseLabelOp.from_polynomial_tensor() constructor for one of BosonicOp, FermionicOp, SpinOp, or VibrationalOp, the coefficient for the constant term was a 0d Tensor object rather than a number. This has been fixed.
  • The ElectronicStructureProblem.reference_energy is now properly propagated to the ElectronicStructureResult.hartree_fock_energy.
  • Fixes the logic of the InterleavedQubitMapper to 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.copy and copy.deepcopy operations for the Tensor class.
  • Fixes a regression in the performance of the map() method
  • Compatibility fix to support optional sparse install under Python 3.11.
  • Fixed the support of use_pauli_sum_op in the UCC and UVCC classes as well as their extensions. This requires version 0.24 or higher of the qiskit-terra package.