Algorithms Migration Guide#
TL;DR#
The qiskit.algorithms
module has been fully refactored to use the primitives
, for circuit execution, instead of the QuantumInstance
, which is now deprecated.
There have been 3 types of refactoring:
Algorithms refactored in a new location to support
primitives
. These algorithms have the same class names as theQuantumInstance
-based ones but are in a new sub-package.Atención
Careful with import paths!! The legacy algorithms are still importable directly from
qiskit.algorithms
. Until the legacy imports are removed, this convenience import is not available for the refactored algorithms. Thus, to import the refactored algorithms you must always specify the full import path (e.g.,from qiskit.algorithms.eigensolvers import VQD
)Algorithms refactored in-place (same namespace) to support both
QuantumInstance
andprimitives
. In the future, the use ofQuantumInstance
will be removed.Algorithms that were deprecated and are now removed entirely from
qiskit.algorithms
. These are algorithms that do not currently serve as building blocks for applications. Their main value is educational, and as such, will be kept as tutorials in the qiskit textbook. You can consult the tutorials in the following links:
The remainder of this migration guide will focus on the algorithms with migration alternatives within
qiskit.algorithms
, that is, those under refactoring types 1 and 2.
Antecedentes#
Back to TL;DR
The qiskit.algorithms
module was originally built on top of the qiskit.opflow
library and the
QuantumInstance
utility. The development of the primitives
introduced a higher-level execution paradigm, with the Estimator
for computation of
expectation values for observables, and Sampler
for executing circuits and returning probability
distributions. These tools allowed to refactor the qiskit.algorithms
module, and deprecate both
qiskit.opflow
and QuantumInstance
.
Atención
The transition away from qiskit.opflow
affects the classes that algorithms take as part of the problem
setup. As a rule of thumb, most qiskit.opflow
dependencies have a direct qiskit.quantum_info
replacement. One common example is the class qiskit.opflow.PauliSumOp
, used to define Hamiltonians
(for example, to plug into VQE), that can be replaced by qiskit.quantum_info.SparsePauliOp
.
For information on how to migrate other opflow
objects, you can refer to the
Opflow migration guide.
For further background and detailed migration steps, see the:
How to choose a primitive configuration for your algorithm#
Back to TL;DR
The classes in
qiskit.algorithms
are initialized with any implementation of qiskit.primitive.BaseSampler
or class:qiskit.primitive.BaseEstimator.
Once the kind of primitive is known, you can choose between the primitive implementations that better adjust to your case. For example:
For quick prototyping, you can use the reference implementations of primitives included in Qiskit:
qiskit.primitives.Sampler
andqiskit.primitives.Estimator
.For finer algorithm tuning, a local simulator such as the primitive implementation in Aer:
qiskit_aer.primitives.Sampler
andqiskit_aer.primitives.Estimator
.For executing in quantum hardware you can:
access services with native primitive implementations, such as IBM’s Qiskit Runtime service via
qiskit_ibm_runtime.Sampler
andqiskit_ibm_runtime.Estimator
Wrap any backend with Backend Primitives (
BackendSampler
andBackendEstimator
). These wrappers implement a primitive interface on top of a backend that only supportsBackend.run()
.
For more detailed information and examples, particularly on the use of the Backend Primitives, please refer to the Quantum Instance migration guide.
In this guide, we will cover 3 different common configurations for algorithms that determine which primitive import you should be selecting:
Running an algorithm with a statevector simulator (i.e., using
qiskit.opflow
's legacyMatrixExpectation
), when you want the ideal outcome without shot noise:Reference Primitives with default configuration (see QAOA example):
from qiskit.primitives import Sampler, Estimator
Aer Primitives with statevector simulator (see QAOA example):
from qiskit_aer.primitives import Sampler, Estimator sampler = Sampler(backend_options={"method": "statevector"}) estimator = Estimator(backend_options={"method": "statevector"})
Running an algorithm using a simulator/device with shot noise (i.e., using
qiskit.opflow
's legacyPauliExpectation
):Reference Primitives with shots (see VQE examples):
from qiskit.primitives import Sampler, Estimator sampler = Sampler(options={"shots": 100}) estimator = Estimator(options={"shots": 100}) # or... sampler = Sampler() job = sampler.run(circuits, shots=100) estimator = Estimator() job = estimator.run(circuits, observables, shots=100)
Aer Primitives with default configuration (see VQE examples):
from qiskit_aer.primitives import Sampler, Estimator
IBM’s Qiskit Runtime Primitives with default configuration (see VQD example):
from qiskit_ibm_runtime import Sampler, Estimator
3. Running an algorithm on an Aer simulator using a custom instruction (i.e., using qiskit.opflow
's legacy
AerPauliExpectation
):
Aer Primitives with
shots=None
,approximation=True
(see TrotterQRTE example):from qiskit_aer.primitives import Sampler, Estimator sampler = Sampler(run_options={"approximation": True, "shots": None}) estimator = Estimator(run_options={"approximation": True, "shots": None})
Minimum Eigensolvers#
Back to TL;DR
The minimum eigensolver algorithms belong to the first type of refactoring listed above
(Algorithms refactored in a new location to support primitives
).
Instead of a QuantumInstance
, qiskit.algorithms.minimum_eigensolvers
are now initialized
using an instance of the Sampler
or Estimator
primitive, depending
on the algorithm. The legacy classes can still be found in qiskit.algorithms.minimum_eigen_solvers
.
Atención
For the qiskit.algorithms.minimum_eigensolvers
classes, depending on the import path,
you will access either the primitive-based or the quantum-instance-based
implementation. You have to be extra-careful, because the class name does not change.
Old import (Quantum Instance based):
from qiskit.algorithms import VQE, QAOA, NumPyMinimumEigensolver
New import (Primitives based):
from qiskit.algorithms.minimum_eigensolvers import VQE, SamplingVQE, QAOA, NumPyMinimumEigensolver
VQE#
The legacy qiskit.algorithms.minimum_eigen_solvers.VQE
class has now been split according to the use-case:
For general-purpose Hamiltonians, you can use the Estimator-based
qiskit.algorithms.minimum_eigensolvers.VQE
class.If you have a diagonal Hamiltonian, and would like the algorithm to return a sampling of the state, you can use the new Sampler-based
qiskit.algorithms.minimum_eigensolvers.SamplingVQE
algorithm. This could formerly be realized using the legacyVQE
withCVaRExpectation
.
Nota
In addition to taking in an Estimator
instance instead of a QuantumInstance
,
the new VQE
signature has undergone the following changes:
The
expectation
andinclude_custom
parameters have been removed, as this functionality is now defined at theEstimator
level.The
gradient
parameter now takes in an instance of a primitive-based gradient class fromqiskit.algorithms.gradients
instead of the legacyqiskit.opflow.gradients.Gradient
class.Se eliminó el parámetro
max_evals_grouped
, ya que se puede establecer directamente en la clase de optimizador.Los
estimator
,ansatz
yoptimizer
son los únicos parámetros que se pueden definir posicionalmente (y en este orden), todos los demás se han convertido en argumentos de solo palabras clave.
Nota
The new VQEResult
class does not include the state anymore, as
this output was only useful in the case of diagonal operators. However, if it is available as part of the new
SamplingVQE
’s SamplingVQEResult
.
For complete code examples, see the following updated tutorials:
QAOA#
The legacy qiskit.algorithms.minimum_eigen_solvers.QAOA
class used to extend
qiskit.algorithms.minimum_eigen_solvers.VQE
, but now, qiskit.algorithms.minimum_eigensolvers.QAOA
extends qiskit.algorithms.minimum_eigensolvers.SamplingVQE
.
For this reason, the new QAOA only supports diagonal operators.
Nota
In addition to taking in an Sampler
instance instead of a QuantumInstance
,
the new QAOA
signature has undergone the following changes:
The
expectation
andinclude_custom
parameters have been removed. In return, theaggregation
parameter has been added (it used to be defined through a customexpectation
).The
gradient
parameter now takes in an instance of a primitive-based gradient class fromqiskit.algorithms.gradients
instead of the legacyqiskit.opflow.gradients.Gradient
class.Se eliminó el parámetro
max_evals_grouped
, ya que se puede establecer directamente en la clase de optimizador.The
sampler
andoptimizer
are the only parameters that can be defined positionally (and in this order), all others have become keyword-only arguments.
Nota
If you want to run QAOA on a non-diagonal operator, you can use the QAOAAnsatz
with
qiskit.algorithms.minimum_eigensolvers.VQE
, but bear in mind there will be no state result.
If your application requires the final probability distribution, you can instantiate a Sampler
and run it with the optimal circuit after VQE
.
For complete code examples, see the following updated tutorials:
NumPyMinimumEigensolver#
Because this is a classical solver, the workflow has not changed between the old and new implementation.
The import has however changed from qiskit.algorithms.minimum_eigen_solvers.NumPyMinimumEigensolver
to qiskit.algorithms.minimum_eigensolvers.NumPyMinimumEigensolver
to conform to the new interfaces
and result classes.
For complete code examples, see the following updated tutorials:
Solucionadores propios#
Back to TL;DR
The eigensolver algorithms also belong to the first type of refactoring
(Algorithms refactored in a new location to support primitives
). Instead of a
QuantumInstance
, qiskit.algorithms.eigensolvers
are now initialized
using an instance of the Sampler
or Estimator
primitive, or
a primitive-based subroutine, depending on the algorithm. The legacy classes can still be found
in qiskit.algorithms.eigen_solvers
.
Atención
For the qiskit.algorithms.eigensolvers
classes, depending on the import path,
you will access either the primitive-based or the quantum-instance-based
implementation. You have to be extra-careful, because the class name does not change.
Old import path (Quantum Instance):
from qiskit.algorithms import VQD, NumPyEigensolver
New import path (Primitives):
from qiskit.algorithms.eigensolvers import VQD, NumPyEigensolver
VQD#
The new qiskit.algorithms.eigensolvers.VQD
class is initialized with an instance of the
Estimator
primitive instead of a QuantumInstance
.
In addition to this, it takes an instance of a state fidelity class from mod:qiskit.algorithms.state_fidelities,
such as the Sampler
-based ComputeUncompute
.
Nota
In addition to taking in an Estimator
instance instead of a QuantumInstance
,
the new VQD
signature has undergone the following changes:
The
expectation
andinclude_custom
parameters have been removed, as this functionality is now defined at theEstimator
level.The custom
fidelity
parameter has been added, and the customgradient
parameter has been removed, as current classes inqiskit.algorithms.gradients
cannot deal with state fidelity gradients.Se eliminó el parámetro
max_evals_grouped
, ya que se puede establecer directamente en la clase de optimizador.The
estimator
,fidelity
,ansatz
andoptimizer
are the only parameters that can be defined positionally (and in this order), all others have become keyword-only arguments.
Nota
Similarly to VQE, the new VQDResult
class does not include
the state anymore. If your application requires the final probability distribution, you can instantiate
a Sampler
and run it with the optimal circuit for the desired excited state
after running VQD
.
For complete code examples, see the following updated tutorial:
NumPyEigensolver#
Similarly to its minimum eigensolver counterpart, because this is a classical solver, the workflow has not changed
between the old and new implementation.
The import has however changed from qiskit.algorithms.eigen_solvers.NumPyEigensolver
to qiskit.algorithms.eigensolvers.MinimumEigensolver
to conform to the new interfaces and result classes.
Time Evolvers#
Back to TL;DR
The time evolvers are the last group of algorithms to undergo the first type of refactoring
(Algorithms refactored in a new location to support primitives
).
Instead of a QuantumInstance
, qiskit.algorithms.time_evolvers
are now initialized
using an instance of the Estimator
primitive. The legacy classes can still be found
in qiskit.algorithms.evolvers
.
On top of the migration, the module has been substantially expanded to include Variational Quantum Time Evolution
(VarQTE
) solvers.
TrotterQRTE#
Atención
For the qiskit.algorithms.time_evolvers.TrotterQRTE
class, depending on the import path,
you will access either the primitive-based or the quantum-instance-based
implementation. You have to be extra-careful, because the class name does not change.
Old import path (Quantum Instance):
from qiskit.algorithms import TrotterQRTE
New import path (Primitives):
from qiskit.algorithms.time_evolvers import TrotterQRTE
Nota
In addition to taking in an Estimator
instance instead of a QuantumInstance
,
the new VQD
signature has undergone the following changes:
The
expectation
parameter has been removed, as this functionality is now defined at theEstimator
level.The
num_timesteps
parameters has been added, to allow to define the number of steps the full evolution time is divided into.
Amplificadores de Amplitud#
Back to TL;DR
The amplitude amplifier algorithms belong to the second type of refactoring (Algorithms refactored in-place).
Instead of a QuantumInstance
, qiskit.algorithms.amplitude_amplifiers
are now initialized
using an instance of any «Sampler» primitive e.g. Sampler
.
Nota
The full qiskit.algorithms.amplitude_amplifiers
module has been refactored in place. No need to
change import paths.
For complete code examples, see the following updated tutorials:
Amplitude Estimators#
Back to TL;DR
Similarly to the amplitude amplifiers, the amplitude estimators also belong to the second type of refactoring
(Algorithms refactored in-place).
Instead of a QuantumInstance
, qiskit.algorithms.amplitude_estimators
are now initialized
using an instance of any «Sampler» primitive e.g. Sampler
.
Nota
The full qiskit.algorithms.amplitude_estimators
module has been refactored in place. No need to
change import paths.
For complete code examples, see the following updated tutorials:
Estimadores de Fase#
Back to TL;DR
Finally, the phase estimators are the last group of algorithms to undergo the first type of refactoring
(Algorithms refactored in-place).
Instead of a QuantumInstance
, qiskit.algorithms.phase_estimators
are now initialized
using an instance of any «Sampler» primitive e.g. Sampler
.
Nota
The full qiskit.algorithms.phase_estimators
module has been refactored in place. No need to
change import paths.
For complete code examples, see the following updated tutorials: