# 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 the`QuantumInstance`

-based ones but are in a new sub-package.Attention

**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`

and`primitives`

. In the future, the use of`QuantumInstance`

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.

## Background¶

*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`

.

Attention

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`

state the base class primitive type (`Sampler`

/`Estimator`

)
they require for their initialization. Once the primitive type is known, you can choose between
four different primitive implementations, depending on how you want to configure your execution:

Using

localstatevector simulators for quick prototyping:Reference Primitivesin`qiskit.primitives`

Using

localAer simulators for finer algorithm tuning:Aer Primitivesin`qiskit_aer.primitives`

Accessing backends using the

Qiskit Runtime Service:Runtime Primitivesin`qiskit_ibm_runtime`

Accessing backends using a

non-Runtime-enabled provider:Backend Primitivesin`qiskit.primitives`

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 legacy`MatrixExpectation`

), 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 legacy`PauliExpectation`

):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

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`

.

Attention

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 legacy`VQE`

with`CVaRExpectation`

.

Note

In addition to taking in an `Estimator`

instance instead of a `QuantumInstance`

,
the new `VQE`

signature has undergone the following changes:

The

`expectation`

and`include_custom`

parameters have been removed, as this functionality is now defined at the`Estimator`

level.The

`gradient`

parameter now takes in an instance of a primitive-based gradient class from`qiskit.algorithms.gradients`

instead of the legacy`qiskit.opflow.gradients.Gradient`

class.The

`max_evals_grouped`

parameter has been removed, as it can be set directly on the optimizer class.The

`estimator`

,`ansatz`

and`optimizer`

are the only parameters that can be defined positionally (and in this order), all others have become keyword-only arguments.

Note

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**.

Note

In addition to taking in an `Sampler`

instance instead of a `QuantumInstance`

,
the new `QAOA`

signature has undergone the following changes:

The

`expectation`

and`include_custom`

parameters have been removed. In return, the`aggregation`

parameter has been added (it used to be defined through a custom`expectation`

).The

`gradient`

parameter now takes in an instance of a primitive-based gradient class from`qiskit.algorithms.gradients`

instead of the legacy`qiskit.opflow.gradients.Gradient`

class.The

`max_evals_grouped`

parameter has been removed, as it can be set directly on the optimizer class.The

`sampler`

and`optimizer`

are the only parameters that can be defined positionally (and in this order), all others have become keyword-only arguments.

Note

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:

## Eigensolvers¶

*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`

.

Attention

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`

.

Note

In addition to taking in an `Estimator`

instance instead of a `QuantumInstance`

,
the new `VQD`

signature has undergone the following changes:

The

`expectation`

and`include_custom`

parameters have been removed, as this functionality is now defined at the`Estimator`

level.The custom

`fidelity`

parameter has been added, and the custom`gradient`

parameter has been removed, as current classes in`qiskit.algorithms.gradients`

cannot deal with state fidelity gradients.The

`max_evals_grouped`

parameter has been removed, as it can be set directly on the optimizer class.The

`estimator`

,`fidelity`

,`ansatz`

and`optimizer`

are the only parameters that can be defined positionally (and in this order), all others have become keyword-only arguments.

Note

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¶

Attention

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`

Note

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 the`Estimator`

level.The

`num_timesteps`

parameters has been added, to allow to define the number of steps the full evolution time is divided into.

## Amplitude Amplifiers¶

*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`

.

Note

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`

.

Note

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:

## Phase Estimators¶

*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`

.

Note

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: