qiskit-documentation/docs/migration-guides/qiskit-algorithms-module.mdx

853 lines
36 KiB
Plaintext

---
title: qiskit.algorithms migration guide
description: How to update your code to use the new interface for `qiskit.algorithms`.
---
# Algorithms migration guide
<Admonition type="caution">
**Deprecation Notice**
This guide precedes the introduction of the V2 primitives interface. Following the introduction of the V2 primitives, some providers have deprecated V1 primitive
implementations in favor of the V2 alternatives. If you are interested in following this guide, we recommend combining it with the
[Migrate to V2 primitives](./v2-primitives) guide to bring your code to the most updated state.
</Admonition>
In Qiskit 0.44 and later releases, the `qiskit.algorithms` module has been superseded by a new standalone library, `qiskit_algorithms`,
available on [GitHub](https://github.com/qiskit-community/qiskit-algorithms) and
[PyPi](https://pypi.org/project/qiskit-algorithms). The `qiskit.algorithms` module was migrated to a
separate package in order to clarify the purpose of Qiskit and make a distinction between the tools and libraries built on top of it.
If your code used `qiskit.algorithms`, follow these steps:
1. Check your code for any uses of the `qiskit.algorithms` module. If you are, follow this guide to
migrate to the primitives-based implementation.
2. After updating your code, run `pip install qiskit-algorithms` and update your imports from
`qiskit.algorithms` to `qiskit_algorithms`.
## Background
The [`qiskit.algorithms`](/api/qiskit/0.46/algorithms) module was originally built on top of the [`qiskit.opflow`](/api/qiskit/0.46/opflow) library and the
[`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance) utility. The development of the [`qiskit.primitives`](/api/qiskit/primitives)
introduced a higher-level execution paradigm, with the Estimator for computing expectation values for observables, and Sampler for executing circuits and returning probability distributions. These tools allowed the [`qiskit.algorithms`](/api/qiskit/0.46/algorithms) module to be refactored, after which,
[`qiskit.opflow`](/api/qiskit/0.46/opflow) and [`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance) were deprecated.
<Admonition type="caution">
The transition away from [`qiskit.opflow`](/api/qiskit/0.46/opflow) affects the classes that algorithms use as part of the problem
setup. Most [`qiskit.opflow`](/api/qiskit/0.46/opflow) dependencies have a direct [`qiskit.quantum_info`](/api/qiskit/quantum_info)
replacement. One common example is the class [`qiskit.opflow.primitive_ops.PauliSumOp`](/api/qiskit/0.46/qiskit.opflow.primitive_ops.PauliSumOp), used to define Hamiltonians
(for example, to plug into VQE), which can be replaced by [`qiskit.quantum_info.SparsePauliOp`](/api/qiskit/qiskit.quantum_info.SparsePauliOp).
For information to migrate other [`qiskit.opflow`](/api/qiskit/0.46/opflow) objects, refer to the [Opflow migration guide](./qiskit-opflow-module).
</Admonition>
For further background and detailed migration steps, see these guides:
- [Opflow migration guide](./qiskit-opflow-module)
- [QuantumInstance migration guide](./qiskit-quantum-instance)
## What has changed
The [`qiskit.algorithms`](/api/qiskit/0.46/algorithms) module has been fully refactored to use the [`qiskit.primitives`](/api/qiskit/primitives), for circuit execution, instead of the [`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance), which is now deprecated.
There have been three types of refactoring:
1. Algorithms that were refactored in a new location to support [`qiskit.primitives`](/api/qiskit/primitives). These algorithms have the same
class names as the [`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance)-based ones but are in a new subpackage.
<Admonition type="caution">
Be careful with import paths. The legacy algorithms can still be imported from
[`qiskit.algorithms`](/api/qiskit/0.46/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 specify the full import path. For example, `from qiskit.algorithms.eigensolvers import VQD`.
</Admonition>
- [Minimum Eigensolvers](#minimum-eigensolvers)
- [Eigensolvers](#eigensolvers)
- [Time Evolvers](#time-evolvers)
2. Algorithms that were refactored in-place (same namespace) to support both [`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance) and
[`qiskit.primitives`](/api/qiskit/primitives). In the future, [`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance) will be removed.
- [Amplitude Amplifiers](#amplitude-amplifiers)
- [Amplitude Estimators](#amplitude-estimators)
- [Phase Estimators](#phase-estimators)
3. Algorithms that were deprecated and are now removed entirely from [`qiskit.algorithms`](/api/qiskit/0.46/algorithms). These are algorithms that do not serve
as building blocks for applications and are only valuable for education, as described in the following tutorials:
- [Linear Solvers (HHL)](https://github.com/Qiskit/textbook/blob/main/notebooks/ch-applications/hhl_tutorial.ipynb) ,
- [Factorizers (Shor)](https://github.com/Qiskit/textbook/blob/main/notebooks/ch-algorithms/shor.ipynb)
This migration guide focuses on the algorithms with migration alternatives within
[`qiskit.algorithms`](/api/qiskit/0.46/algorithms), that is, refactoring types 1 and 2.
## How to choose a primitive configuration for your algorithm
The classes in
[`qiskit.algorithms`](/api/qiskit/0.46/algorithms) are initialized with any implementation of [`qiskit.primitives.BaseSampler`](/api/qiskit/0.46/qiskit.primitives.BaseSampler) or [`qiskit.primitives.BaseEstimator`](/api/qiskit/0.46/qiskit.primitives.BaseEstimator).
Once you know which primitive you want to use, choose the primitive implementation that meets your needs. For example:
* For quick prototyping, use the reference implementations of primitives included in Qiskit: [`qiskit.primitives.Sampler`](/api/qiskit/qiskit.primitives.Sampler) and [`qiskit.primitives.Estimator`](/api/qiskit/qiskit.primitives.Estimator).
* For finer algorithm tuning, use a local simulator such as the primitive implementation in Aer: [`qiskit_aer.primitives.Sampler`](https://qiskit.org/ecosystem/aer/stubs/qiskit_aer.primitives.Sampler.html) and [`qiskit_aer.primitives.Estimator`](https://qiskit.org/ecosystem/aer/stubs/qiskit_aer.primitives.Estimator.html).
* For running on quantum hardware choose from these options:
- Access services with native primitive implementations, such as the Qiskit Runtime service, by using [`qiskit_ibm_runtime.Sampler`](/api/qiskit-ibm-runtime/0.26/qiskit_ibm_runtime.Sampler) and [`qiskit_ibm_runtime.Estimator`.](/api/qiskit-ibm-runtime/0.26/qiskit_ibm_runtime.Estimator)
- Wrap any QPU (quantum processing unti) with `Backend` primitives ([`qiskit.primitives.BackendSampler`](/api/qiskit/qiskit.primitives.BackendSampler) and [`qiskit.primitives.BackendEstimator`](/api/qiskit/qiskit.primitives.BackendEstimator)). These wrappers implement a primitive interface on top of a backend that only supports `backend.run()`.
For detailed information and examples, particularly on the use of the `Backend` primitives, refer to
the [QuantumInstance migration guide](./qiskit-quantum-instance).
This guide describes these common configurations for algorithms that determine which primitive import to use:
* Running an algorithm with a statevector simulator when you want the ideal outcome without shot noise. For example, using the [`qiskit.opflow`](/api/qiskit/0.46/opflow) legacy
[`qiskit.opflow.expectations.MatrixExpectation`](/api/qiskit/0.46/qiskit.opflow.expectations.MatrixExpectation):
- Reference Primitives with default configuration. See [QAOA](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/05_qaoa.ipynb) for an example.
```python
from qiskit.primitives import Sampler, Estimator
```
- Aer Primitives with statevector simulator. See [QAOA](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/05_qaoa.ipynb) for an example.
```python
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 or device with shot noise. For example, using the [`qiskit.opflow`](/api/qiskit/0.46/opflow) legacy [`qiskit.opflow.expectations.PauliExpectation`](/api/qiskit/0.46/qiskit.opflow.expectations.PauliExpectation):
- Reference primitives with shots. See the [VQE](#vqe) examples.
```python
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 the [VQE](#vqe) examples.
```python
from qiskit_aer.primitives import Sampler, Estimator
```
- IBM Qiskit Runtime primitives with default configuration. See [VQD](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/04_vqd.ipynb) for an example.
```python
from qiskit_ibm_runtime import Sampler, Estimator
```
* Running an algorithm on an Aer simulator using a custom instruction. For example, using the [`qiskit.opflow`](/api/qiskit/0.46/opflow) legacy
[`qiskit.opflow.expectations.AerPauliExpectation`](/api/qiskit/0.46/qiskit.opflow.expectations.AerPauliExpectation).
- Aer Primitives with default options. See [TrotterQRTE](#trotterqrte) for examples.
```python
from qiskit_aer.primitives import Sampler, Estimator
sampler = Sampler()
estimator = Estimator()
```
<span id="eigen"></span>
## Minimum Eigensolvers
The minimum eigensolver algorithms were refactored in a new location.
Instead of a [`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance), [`qiskit.algorithms.minimum_eigensolvers`](/api/qiskit/0.46/qiskit.algorithms.minimum_eigensolvers) are now initialized
by using an instance of the [`qiskit.primitives.Sampler`](/api/qiskit/qiskit.primitives.Sampler) or [`qiskit.primitives.Estimator`](/api/qiskit/qiskit.primitives.Estimator) primitive, depending
on the algorithm. The legacy classes can still be found in `qiskit.algorithms.minimum_eigen_solvers`.
<Admonition type="caution">
For the [`qiskit.algorithms.minimum_eigensolvers`](/api/qiskit/0.46/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 careful, because the class name does not change.
- Old import (QuantumInstance-based): `from qiskit.algorithms import VQE, QAOA, NumPyMinimumEigensolver`
- New import (Primitives-based): `from qiskit.algorithms.minimum_eigensolvers import VQE, SamplingVQE, QAOA, NumPyMinimumEigensolver`
</Admonition>
### VQE
The legacy `qiskit.algorithms.minimum_eigen_solvers.VQE` class has now been split according to the use case:
- For general-purpose Hamiltonians, use the Estimator-based [`qiskit.algorithms.minimum_eigensolvers.VQE`](/api/qiskit/0.46/qiskit.algorithms.minimum_eigensolvers.VQE)
class.
- If you have a diagonal Hamiltonian and want the algorithm to return a sampling of the state, use
the new Sampler-based [`qiskit.algorithms.minimum_eigensolvers.SamplingVQE`](/api/qiskit/0.46/qiskit.algorithms.minimum_eigensolvers.SamplingVQE) algorithm. Previously, this was done by using the legacy `qiskit.algorithms.minimum_eigen_solvers.VQE` with
[`qiskit.opflow.expectations.CVaRExpectation`](/api/qiskit/0.46/qiskit.opflow.expectations.CVaRExpectation).
<Admonition type="note">
In addition to taking in an [`qiskit.primitives.Estimator`](/api/qiskit/qiskit.primitives.Estimator) instance instead of a [`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance),
the new [`qiskit.algorithms.minimum_eigensolvers.VQE`](/api/qiskit/0.46/qiskit.algorithms.minimum_eigensolvers.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`](/api/qiskit/0.46/qiskit.algorithms.gradients) instead of the legacy [`qiskit.opflow.gradients.Gradient`](/api/qiskit/0.46/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.
</Admonition>
<Admonition type="note">
The new [`qiskit.algorithms.minimum_eigensolvers.VQEResult`](/api/qiskit/0.46/qiskit.algorithms.minimum_eigensolvers.VQEResult) class does not include the state, as
this output was only useful in the case of diagonal operators. However, it is available as part of the new
[`qiskit.algorithms.minimum_eigensolvers.SamplingVQE`](/api/qiskit/0.46/qiskit.algorithms.minimum_eigensolvers.SamplingVQE) [`qiskit.algorithms.minimum_eigensolvers.SamplingVQEResult`](/api/qiskit/0.46/qiskit.algorithms.minimum_eigensolvers.SamplingVQEResult).
</Admonition>
#### VQE examples
**[Legacy] Using QuantumInstance:**
```python
from qiskit.algorithms import VQE
from qiskit.algorithms.optimizers import SPSA
from qiskit.circuit.library import TwoLocal
from qiskit.opflow import PauliSumOp
from qiskit.utils import QuantumInstance
from qiskit_aer import AerSimulator
ansatz = TwoLocal(2, 'ry', 'cz')
opt = SPSA(maxiter=50)
# shot-based simulation
backend = AerSimulator()
qi = QuantumInstance(backend=backend, shots=2048, seed_simulator=42)
vqe = VQE(ansatz, optimizer=opt, quantum_instance=qi)
hamiltonian = PauliSumOp.from_list([("XX", 1), ("XY", 1)])
result = vqe.compute_minimum_eigenvalue(hamiltonian)
print(result.eigenvalue)
```
```python
(-0.9775390625+0j)
```
**[Updated] Using primitives:**
```python
from qiskit.algorithms.minimum_eigensolvers import VQE # new import!!!
from qiskit.algorithms.optimizers import SPSA
from qiskit.circuit.library import TwoLocal
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives import Estimator
from qiskit_aer.primitives import Estimator as AerEstimator
ansatz = TwoLocal(2, 'ry', 'cz')
opt = SPSA(maxiter=50)
# shot-based simulation
estimator = Estimator(options={"shots": 2048})
vqe = VQE(estimator, ansatz, opt)
# another option
aer_estimator = AerEstimator(run_options={"shots": 2048, "seed": 42})
vqe = VQE(aer_estimator, ansatz, opt)
hamiltonian = SparsePauliOp.from_list([("XX", 1), ("XY", 1)])
result = vqe.compute_minimum_eigenvalue(hamiltonian)
print(result.eigenvalue)
```
```python
-0.986328125
```
#### VQE applying CVaR (SamplingVQE) example
**[Legacy] Using QuantumInstance:**
```python
from qiskit.algorithms import VQE
from qiskit.algorithms.optimizers import SLSQP
from qiskit.circuit.library import TwoLocal
from qiskit.opflow import PauliSumOp, CVaRExpectation
from qiskit.utils import QuantumInstance
from qiskit_aer import AerSimulator
ansatz = TwoLocal(2, 'ry', 'cz')
opt = SLSQP(maxiter=50)
# shot-based simulation
backend = AerSimulator()
qi = QuantumInstance(backend=backend, shots=2048)
expectation = CVaRExpectation(alpha=0.2)
vqe = VQE(ansatz, optimizer=opt, expectation=expectation, quantum_instance=qi)
# diagonal Hamiltonian
hamiltonian = PauliSumOp.from_list([("ZZ",1), ("IZ", -0.5), ("II", 0.12)])
result = vqe.compute_minimum_eigenvalue(hamiltonian)
print(result.eigenvalue.real)
```
```python
-1.38
```
**[Updated] Using primitives:**
```python
from qiskit.algorithms.minimum_eigensolvers import SamplingVQE # new import!!!
from qiskit.algorithms.optimizers import SPSA
from qiskit.circuit.library import TwoLocal
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives import Sampler
from qiskit_aer.primitives import Sampler as AerSampler
ansatz = TwoLocal(2, 'ry', 'cz')
opt = SPSA(maxiter=50)
# shot-based simulation
sampler = Sampler(options={"shots": 2048})
vqe = SamplingVQE(sampler, ansatz, opt, aggregation=0.2)
# another option
aer_sampler = AerSampler(run_options={"shots": 2048, "seed": 42})
vqe = SamplingVQE(aer_sampler, ansatz, opt, aggregation=0.2)
# diagonal Hamiltonian
hamiltonian = SparsePauliOp.from_list([("ZZ",1), ("IZ", -0.5), ("II", 0.12)])
result = vqe.compute_minimum_eigenvalue(hamiltonian)
print(result.eigenvalue.real)
```
```python
-1.38
```
For complete code examples, see the following updated tutorials:
- [VQE introduction](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/01_algorithms_introduction.ipynb)
- [VQE, callback, gradients, initial point](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/02_vqe_advanced_options.ipynb)
- [VQE with Aer primitives](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/03_vqe_simulation_with_noise.ipynb)
### QAOA
The new QAOA only supports diagonal operators. This is because the legacy `qiskit.algorithms.minimum_eigen_solvers.QAOA` class extended
`qiskit.algorithms.minimum_eigen_solvers.VQE`, but now, [`qiskit.algorithms.minimum_eigensolvers.QAOA`](/api/qiskit/0.46/qiskit.algorithms.minimum_eigensolvers.QAOA)
extends [`qiskit.algorithms.minimum_eigensolvers.SamplingVQE`](/api/qiskit/0.46/qiskit.algorithms.minimum_eigensolvers.SamplingVQE).
<Admonition type="note">
In addition to taking in a [`qiskit.primitives.Sampler`](/api/qiskit/qiskit.primitives.Sampler) instance instead of a [`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance),
the new [`qiskit.algorithms.minimum_eigensolvers.QAOA`](/api/qiskit/0.46/qiskit.algorithms.minimum_eigensolvers.QAOA) signature has undergone the following changes:
* The `expectation` and `include_custom` parameters have been removed and the `aggregation`
parameter has been added. This was previously defined through a custom `expectation` parameter.
* The `gradient` parameter now takes in an instance of a primitive-based gradient class from
[`qiskit.algorithms.gradients`](/api/qiskit/0.46/qiskit.algorithms.gradients) instead of the legacy [`qiskit.opflow.gradients.Gradient`](/api/qiskit/0.46/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` parameters are the only parameters that can be defined positionally
(and in this order). All others have become keyword-only arguments.
</Admonition>
<Admonition type="note">
If you want to run QAOA on a non-diagonal operator, use the [`qiskit.circuit.library.QAOAAnsatz`](/api/qiskit/qiskit.circuit.library.QAOAAnsatz) with
[`qiskit.algorithms.minimum_eigensolvers.VQE`](/api/qiskit/0.46/qiskit.algorithms.minimum_eigensolvers.VQE), but there will be no state result.
If your application requires the final probability distribution, instantiate `SamplerV2`
and run it with the optimal circuit after [`qiskit.algorithms.minimum_eigensolvers.VQE`](/api/qiskit/0.46/qiskit.algorithms.minimum_eigensolvers.VQE).
</Admonition>
#### QAOA example
**[Legacy] Using QuantumInstance:**
```python
from qiskit.algorithms import QAOA
from qiskit.algorithms.optimizers import COBYLA
from qiskit.opflow import PauliSumOp
from qiskit.utils import QuantumInstance
from qiskit_aer import AerSimulator
# exact statevector simulation
backend = AerSimulator()
qi = QuantumInstance(backend=backend, shots=None,
seed_simulator = 42, seed_transpiler = 42,
backend_options={"method": "statevector"})
optimizer = COBYLA()
qaoa = QAOA(optimizer=optimizer, reps=2, quantum_instance=qi)
# diagonal operator
qubit_op = PauliSumOp.from_list([("ZIII", 1),("IZII", 1), ("IIIZ", 1), ("IIZI", 1)])
result = qaoa.compute_minimum_eigenvalue(qubit_op)
print(result.eigenvalue.real)
```
```python
-4.0
```
**[Updated] Using primitives:**
```python
from qiskit.algorithms.minimum_eigensolvers import QAOA
from qiskit.algorithms.optimizers import COBYLA
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives import Sampler
from qiskit_aer.primitives import Sampler as AerSampler
# exact statevector simulation
sampler = Sampler()
# another option
sampler = AerSampler(backend_options={"method": "statevector"},
run_options={"shots": None, "seed": 42})
optimizer = COBYLA()
qaoa = QAOA(sampler, optimizer, reps=2)
# diagonal operator
qubit_op = SparsePauliOp.from_list([("ZIII", 1),("IZII", 1), ("IIIZ", 1), ("IIZI", 1)])
result = qaoa.compute_minimum_eigenvalue(qubit_op)
print(result.eigenvalue)
```
```python
-3.999999832366272
```
For complete code examples, see the updated [QAOA tutorial.](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/05_qaoa.ipynb)
### NumPyMinimumEigensolver
Because this is a classical solver, the workflow has not changed between the old and new implementation.
However, the import has changed from `qiskit.algorithms.minimum_eigen_solvers.NumPyMinimumEigensolver`
to [`qiskit.algorithms.minimum_eigensolvers.NumPyMinimumEigensolver`](/api/qiskit/0.46/qiskit.algorithms.minimum_eigensolvers.NumPyMinimumEigensolver) to conform to the new interfaces
and result classes.
#### NumPyMinimumEigensolver example
**[Legacy] Using QuantumInstance:**
```python
from qiskit.algorithms import NumPyMinimumEigensolver
from qiskit.opflow import PauliSumOp
solver = NumPyMinimumEigensolver()
hamiltonian = PauliSumOp.from_list([("XX", 1), ("XY", 1)])
result = solver.compute_minimum_eigenvalue(hamiltonian)
print(result.eigenvalue)
```
```python
-1.4142135623730958
```
**[Updated] Using primitives:**
```python
from qiskit.algorithms.minimum_eigensolvers import NumPyMinimumEigensolver
from qiskit.quantum_info import SparsePauliOp
solver = NumPyMinimumEigensolver()
hamiltonian = SparsePauliOp.from_list([("XX", 1), ("XY", 1)])
result = solver.compute_minimum_eigenvalue(hamiltonian)
print(result.eigenvalue)
```
```python
-1.414213562373095
```
For complete code examples, see the updated [VQE, callback, gradients, initial point tutorial.](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/02_vqe_advanced_options.ipynb)
<span id="eigensolvers"></span>
## Eigensolvers
The eigensolver algorithms were refactored in a new location. Instead of using
[`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance), [`qiskit.algorithms.eigensolvers`](/api/qiskit/0.46/qiskit.algorithms.eigensolvers) are now initialized
using an instance of the [`qiskit.primitives.Sampler`](/api/qiskit/qiskit.primitives.Sampler) or [`qiskit.primitives.Estimator`](/api/qiskit/qiskit.primitives.Estimator) primitive, or
a primitive-based subroutine, depending on the algorithm. The legacy classes can still be found
in `qiskit.algorithms.eigen_solvers`.
<Admonition type="caution">
For the [`qiskit.algorithms.eigensolvers`](/api/qiskit/0.46/qiskit.algorithms.eigensolvers) classes, depending on the import path,
you will access either the primitive-based or the QuantumInstance-based
implementation. You have to be careful, because the class name is the same.
- Old import path (QuantumInstance): `from qiskit.algorithms import VQD, NumPyEigensolver`
- New import path (primitives): `from qiskit.algorithms.eigensolvers import VQD, NumPyEigensolver`
</Admonition>
### VQD
The new [`qiskit.algorithms.eigensolvers.VQD`](/api/qiskit/0.46/qiskit.algorithms.eigensolvers.VQD) class is initialized with an instance of the
[`qiskit.primitives.Estimator`](/api/qiskit/qiskit.primitives.Estimator) primitive instead of a [`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance).
It also takes an instance of a state fidelity class from mod:`qiskit.algorithms.state_fidelities`,
such as the [`qiskit.primitives.Sampler`](/api/qiskit/qiskit.primitives.Sampler)-based [`qiskit.algorithms.state_fidelities.ComputeUncompute`](/api/qiskit/0.46/qiskit.algorithms.state_fidelities.ComputeUncompute).
<Admonition type="note">
In addition to taking in a [`qiskit.primitives.Estimator`](/api/qiskit/qiskit.primitives.Estimator) instance instead of a [`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance),
the new [`qiskit.algorithms.eigensolvers.VQD`](/api/qiskit/0.46/qiskit.algorithms.eigensolvers.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 because current classes in [`qiskit.algorithms.gradients`](/api/qiskit/0.46/qiskit.algorithms.gradients) cannot use state fidelity
gradients.
* The `max_evals_grouped` parameter has been removed because it can be set directly on the `optimizer` class.
* The `estimator`, `fidelity`, `ansatz` and `optimizer` parameters are the only parameters that can be defined positionally
(and in this order). All others have become keyword-only arguments.
</Admonition>
<Admonition type="note">
Similar to VQE, the new [`qiskit.algorithms.eigensolvers.VQDResult`](/api/qiskit/0.46/qiskit.algorithms.eigensolvers.VQDResult) class does not include
the state. If your application requires the final probability distribution, instantiate
`SamplerV2` and run it with the optimal circuit for the desired excited state
after running [`qiskit.algorithms.eigensolvers.VQD`](/api/qiskit/0.46/qiskit.algorithms.eigensolvers.VQD).
</Admonition>
#### VQD Example
**[Legacy] Using QuantumInstance:**
```python
from qiskit import IBMQ
from qiskit.algorithms import VQD
from qiskit.algorithms.optimizers import SLSQP
from qiskit.circuit.library import TwoLocal
from qiskit.opflow import PauliSumOp
from qiskit.utils import QuantumInstance
ansatz = TwoLocal(3, rotation_blocks=["ry", "rz"], entanglement_blocks="cz", reps=1)
optimizer = SLSQP(maxiter=10)
hamiltonian = PauliSumOp.from_list([("XXZ", 1), ("XYI", 1)])
# example executing in cloud simulator
provider = IBMQ.load_account()
backend = provider.get_backend("ibmq_qasm_simulator")
qi = QuantumInstance(backend=backend)
vqd = VQD(ansatz, k=3, optimizer=optimizer, quantum_instance=qi)
result = vqd.compute_eigenvalues(operator=hamiltonian)
print(result.eigenvalues)
```
```python
[ 0.01765114+0.0e+00j -0.58507654+0.0e+00j -0.15003642-2.8e-17j]
```
**[Updated] Using primitives:**
```python
from qiskit_ibm_runtime import Sampler, Estimator, QiskitRuntimeService, Session
from qiskit.algorithms.eigensolvers import VQD
from qiskit.algorithms.optimizers import SLSQP
from qiskit.algorithms.state_fidelities import ComputeUncompute
from qiskit.circuit.library import TwoLocal
from qiskit.quantum_info import SparsePauliOp
ansatz = TwoLocal(3, rotation_blocks=["ry", "rz"], entanglement_blocks="cz", reps=1)
optimizer = SLSQP(maxiter=10)
hamiltonian = SparsePauliOp.from_list([("XXZ", 1), ("XYI", 1)])
# example executing on a QPU
service = QiskitRuntimeService(channel="ibm_quantum")
backend = service.backend("ibm_sherbrooke")
with Session(backend=backend) as session:
estimator = Estimator()
sampler = Sampler()
fidelity = ComputeUncompute(sampler)
vqd = VQD(estimator, fidelity, ansatz, optimizer, k=3)
result = vqd.compute_eigenvalues(operator=hamiltonian)
print(result.eigenvalues)
```
```python
[ 0.01765114+0.0e+00j -0.58507654+0.0e+00j -0.15003642-2.8e-17j]
```
For complete code examples, see the updated [VQD tutorial.](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/04_vqd.ipynb)
### NumPyEigensolver
Similarly to its minimum eigensolver counterpart, because this is a classical solver, the workflow has not changed
between the old and new implementation.
However, the import has changed from `qiskit.algorithms.eigen_solvers.NumPyEigensolver`
to [`qiskit.algorithms.eigensolvers.NumPyEigensolver`](/api/qiskit/0.46/qiskit.algorithms.eigensolvers.NumPyEigensolver) to conform to the new interfaces and result classes.
#### NumPyEigensolver Example
**[Legacy]:**
```python
from qiskit.algorithms import NumPyEigensolver
from qiskit.opflow import PauliSumOp
solver = NumPyEigensolver(k=2)
hamiltonian = PauliSumOp.from_list([("XX", 1), ("XY", 1)])
result = solver.compute_eigenvalues(hamiltonian)
print(result.eigenvalues)
```
```python
[-1.41421356 -1.41421356]
```
**[Updated]:**
```python
from qiskit.algorithms.eigensolvers import NumPyEigensolver
from qiskit.quantum_info import SparsePauliOp
solver = NumPyEigensolver(k=2)
hamiltonian = SparsePauliOp.from_list([("XX", 1), ("XY", 1)])
result = solver.compute_eigenvalues(hamiltonian)
print(result.eigenvalues)
```
```python
[-1.41421356 -1.41421356]
```
<span id="time"></span>
## Time Evolvers
The time evolvers were refactored in a new location.
Instead of using a [`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance), `qiskit.algorithms.time_evolvers` are now initialized
using a [`qiskit.primitives.Estimator`](/api/qiskit/qiskit.primitives.Estimator) primitive instance. The legacy classes can still be found
in `qiskit.algorithms.evolvers`.
In addition to the migration, the module has been substantially expanded to include Variational Quantum Time Evolution
(`qiskit.algorithms.time_evolvers.VarQTE`) solvers.
### TrotterQRTE
<Admonition type="caution">
For the `TrotterQRTE` class, depending on the import path,
you will access either the primitive-based or the QuantumInstance-based
implementation. You have to be careful because the class name did not change.
- Old import path (QuantumInstance): `from qiskit.algorithms import TrotterQRTE`
- New import path (Primitives): `from qiskit.algorithms.time_evolvers import TrotterQRTE`
</Admonition>
<Admonition type="note">
In addition to taking in a [`qiskit.primitives.Estimator`](/api/qiskit/qiskit.primitives.Estimator) instance instead of a [`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance),
the new [`qiskit.algorithms.eigensolvers.VQD`](/api/qiskit/0.46/qiskit.algorithms.eigensolvers.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` parameter has been added so you can define how many steps to divide the full evolution time in to.
</Admonition>
#### TrotterQRTE Example
**[Legacy] Using QuantumInstance:**
```python
from qiskit.algorithms import EvolutionProblem, TrotterQRTE
from qiskit.circuit import QuantumCircuit
from qiskit.opflow import PauliSumOp, AerPauliExpectation
from qiskit.utils import QuantumInstance
from qiskit_aer import AerSimulator
operator = PauliSumOp.from_list([("X", 1),("Z", 1)])
initial_state = QuantumCircuit(1) # zero
time = 1
evolution_problem = EvolutionProblem(operator, 1, initial_state)
# Aer simulator using custom instruction
backend = AerSimulator()
quantum_instance = QuantumInstance(backend=backend)
expectation = AerPauliExpectation()
# LieTrotter with 1 rep
trotter_qrte = TrotterQRTE(expectation=expectation, quantum_instance=quantum_instance)
evolved_state = trotter_qrte.evolve(evolution_problem).evolved_state
print(evolved_state)
```
```text
CircuitStateFn(
┌─────────────────────┐
q: ┤ exp(-it (X + Z))(1) ├
└─────────────────────┘
)
```
**[Updated] Using primitives:**
```python
from qiskit.algorithms.time_evolvers import TimeEvolutionProblem, TrotterQRTE # note new import!!!
from qiskit.circuit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit_aer.primitives import Estimator as AerEstimator
operator = SparsePauliOp.from_list([("X", 1),("Z", 1)])
initial_state = QuantumCircuit(1) # zero
time = 1
evolution_problem = TimeEvolutionProblem(operator, 1, initial_state)
# Aer simulator using custom instruction
estimator = AerEstimator()
# LieTrotter with 1 rep
trotter_qrte = TrotterQRTE(estimator=estimator)
evolved_state = trotter_qrte.evolve(evolution_problem).evolved_state
print(evolved_state.decompose())
```
```text
┌───────────┐┌───────────┐
q: ┤ exp(it X) ├┤ exp(it Z) ├
└───────────┘└───────────┘
```
<span id="amplitude"></span>
## Amplitude amplifiers
The amplitude amplifier algorithms were refactored in-place.
Instead of a [`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance), `qiskit.algorithms.amplitude_amplifiers` are now initialized
using an instance of any Sampler primitive. That is, [`qiskit.primitives.Sampler`](/api/qiskit/qiskit.primitives.Sampler).
<Admonition type="note">
The full `qiskit.algorithms.amplitude_amplifiers` module has been refactored in place. Therefore, you don't need to
change import paths.
</Admonition>
### Grover example
**[Legacy] Using QuantumInstance:**
```python
from qiskit.algorithms import Grover
from qiskit.utils import QuantumInstance
qi = QuantumInstance(backend=backend)
grover = Grover(quantum_instance=qi)
```
**[Updated] Using primitives:**
```python
from qiskit.algorithms import Grover
from qiskit.primitives import Sampler
grover = Grover(sampler=Sampler())
```
For complete code examples, see the following updated tutorials:
- [Amplitude Amplification and Grover](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/06_grover.ipynb)
- [Grover Examples](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/07_grover_examples.ipynb)
<span id="amp-estimate"></span>
## Amplitude estimators
Similarly to the amplitude amplifiers, the amplitude estimators were refactored in-place.
Instead of a [`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance), `qiskit.algorithms.amplitude_estimators` are now initialized
using an instance of any Sampler primitive. That is, [`qiskit.primitives.Sampler`](/api/qiskit/qiskit.primitives.Sampler).
<Admonition type="note">
The full `qiskit.algorithms.amplitude_estimators` module has been refactored in place. You do not need to
change import paths.
</Admonition>
### IAE example
**[Legacy] Using QuantumInstance:**
```python
from qiskit.algorithms import IterativeAmplitudeEstimation
from qiskit.utils import QuantumInstance
qi = QuantumInstance(backend=backend)
iae = IterativeAmplitudeEstimation(
epsilon_target=0.01, # target accuracy
alpha=0.05, # width of the confidence interval
quantum_instance=qi
)
```
**[Updated] Using primitives:**
```python
from qiskit.algorithms import IterativeAmplitudeEstimation
from qiskit.primitives import Sampler
iae = IterativeAmplitudeEstimation(
epsilon_target=0.01, # target accuracy
alpha=0.05, # width of the confidence interval
sampler=Sampler()
)
```
For a complete code example, see the updated [Amplitude Estimation tutorial.](https://qiskit.org/ecosystem/finance/tutorials/00_amplitude_estimation.html)
<span id="phase"></span>
## Phase estimators
The phase estimators were refactored in-place.
Instead of a [`qiskit.utils.QuantumInstance`](/api/qiskit/0.46/qiskit.utils.QuantumInstance), `qiskit.algorithms.phase_estimators` are now initialized by
using an instance of any Sampler primitive. That is, [`qiskit.primitives.Sampler`](/api/qiskit/qiskit.primitives.Sampler).
<Admonition type="note">
The full `qiskit.algorithms.phase_estimators` module has been refactored in place. Therefore, you do not need to change import paths.
</Admonition>
### IPE example
**[Legacy] Using QuantumInstance:**
```python
from qiskit.algorithms import IterativePhaseEstimation
from qiskit.utils import QuantumInstance
qi = QuantumInstance(backend=backend)
ipe = IterativePhaseEstimation(
num_iterations=num_iter,
quantum_instance=qi
)
```
**[Updated] Using primitives:**
```python
from qiskit.algorithms import IterativePhaseEstimation
from qiskit.primitives import Sampler
ipe = IterativePhaseEstimation(
num_iterations=num_iter,
sampler=Sampler()
)
```
For a complete code examples, see the updated [Iterative phase estimation tutorial.](https://github.com/Qiskit/qiskit-tutorials/blob/master/tutorials/algorithms/09_IQPE.ipynb)