Skip to main contentIBM Quantum Documentation Preview
This is a preview build of IBM Quantum™ documentation. Refer to docs.quantum.ibm.com for the official documentation.

Algorithms migration guide

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 guide to bring your code to the most updated state.

In Qiskit 0.44 and later releases, the qiskit.algorithms module has been superseded by a new standalone library, qiskit_algorithms, available on GitHub and PyPi. 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 module was originally built on top of the qiskit.opflow library and the qiskit.utils.QuantumInstance utility. The development of the 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 module to be refactored, after which, qiskit.opflow and qiskit.utils.QuantumInstance were deprecated.

Caution

The transition away from qiskit.opflow affects the classes that algorithms use as part of the problem setup. Most qiskit.opflow dependencies have a direct qiskit.quantum_info replacement. One common example is the class qiskit.opflow.primitive_ops.PauliSumOp, used to define Hamiltonians (for example, to plug into VQE), which can be replaced by qiskit.quantum_info.SparsePauliOp. For information to migrate other qiskit.opflow objects, refer to the Opflow migration guide.

For further background and detailed migration steps, see these guides:


What has changed

The qiskit.algorithms module has been fully refactored to use the qiskit.primitives, for circuit execution, instead of the 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. These algorithms have the same class names as the qiskit.utils.QuantumInstance-based ones but are in a new subpackage.
Caution

Be careful with import paths. The legacy algorithms can still be imported 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 specify the full import path. For example, from qiskit.algorithms.eigensolvers import VQD.

  1. Algorithms that were refactored in-place (same namespace) to support both qiskit.utils.QuantumInstance and qiskit.primitives. In the future, qiskit.utils.QuantumInstance will be removed.
  1. Algorithms that were deprecated and are now removed entirely from qiskit.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:

This migration guide focuses on the algorithms with migration alternatives within qiskit.algorithms, that is, refactoring types 1 and 2.


How to choose a primitive configuration for your algorithm

The classes in qiskit.algorithms are initialized with any implementation of qiskit.primitives.BaseSampler or qiskit.primitives.BaseEstimator.

Once you know which primitive you want to use, choose the primitive implementation that meets your needs. For example:

For detailed information and examples, particularly on the use of the Backend primitives, refer to the QuantumInstance migration guide.

This guide describes these common configurations for algorithms that determine which primitive import to use:

  • Reference Primitives with default configuration. See QAOA for an example.
from qiskit.primitives import Sampler, Estimator
  • Aer Primitives with statevector simulator. See QAOA for an example.
from qiskit_aer.primitives import Sampler, Estimator
 
sampler = Sampler(backend_options={"method": "statevector"})
estimator = Estimator(backend_options={"method": "statevector"})
  • Reference primitives with shots. See the 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 the VQE examples.
from qiskit_aer.primitives import Sampler, Estimator
  • IBM Qiskit Runtime primitives with default configuration. See VQD for an example.
from qiskit_ibm_runtime import Sampler, Estimator
  • Aer Primitives with default options. See TrotterQRTE for examples.
from qiskit_aer.primitives import Sampler, Estimator
 
sampler = Sampler()
estimator = Estimator()

Minimum Eigensolvers

The minimum eigensolver algorithms were refactored in a new location. Instead of a qiskit.utils.QuantumInstance, qiskit.algorithms.minimum_eigensolvers are now initialized by using an instance of the qiskit.primitives.Sampler or qiskit.primitives.Estimator primitive, depending on the algorithm. The legacy classes can still be found in qiskit.algorithms.minimum_eigen_solvers.

Caution

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

VQE

The legacy qiskit.algorithms.minimum_eigen_solvers.VQE class has now been split according to the use case:

Note

In addition to taking in an qiskit.primitives.Estimator instance instead of a qiskit.utils.QuantumInstance, the new 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 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 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 qiskit.algorithms.minimum_eigensolvers.SamplingVQEResult.

VQE examples

[Legacy] Using QuantumInstance:

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)
(-0.9775390625+0j)

[Updated] Using primitives:

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

VQE applying CVaR (SamplingVQE) example

[Legacy] Using QuantumInstance:

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

[Updated] Using primitives:

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

For complete code examples, see the following updated tutorials:

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 extends qiskit.algorithms.minimum_eigensolvers.SamplingVQE.

Note

In addition to taking in a qiskit.primitives.Sampler instance instead of a qiskit.utils.QuantumInstance, the new 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 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 parameters 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, use the qiskit.circuit.library.QAOAAnsatz with 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.

QAOA example

[Legacy] Using QuantumInstance:

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

[Updated] Using primitives:

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

For complete code examples, see the updated QAOA tutorial.

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 to conform to the new interfaces and result classes.

NumPyMinimumEigensolver example

[Legacy] Using QuantumInstance:

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

[Updated] Using primitives:

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

For complete code examples, see the updated VQE, callback, gradients, initial point tutorial.


Eigensolvers

The eigensolver algorithms were refactored in a new location. Instead of using qiskit.utils.QuantumInstance, qiskit.algorithms.eigensolvers are now initialized using an instance of the qiskit.primitives.Sampler or 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.

Caution

For the 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

VQD

The new qiskit.algorithms.eigensolvers.VQD class is initialized with an instance of the qiskit.primitives.Estimator primitive instead of a 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-based qiskit.algorithms.state_fidelities.ComputeUncompute.

Note

In addition to taking in a qiskit.primitives.Estimator instance instead of a qiskit.utils.QuantumInstance, the new 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 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.
Note

Similar to VQE, the new 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.

VQD Example

[Legacy] Using QuantumInstance:

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)
[ 0.01765114+0.0e+00j -0.58507654+0.0e+00j -0.15003642-2.8e-17j]

[Updated] Using primitives:

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)
[ 0.01765114+0.0e+00j -0.58507654+0.0e+00j -0.15003642-2.8e-17j]

For complete code examples, see the updated VQD 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. However, the import has changed from qiskit.algorithms.eigen_solvers.NumPyEigensolver to qiskit.algorithms.eigensolvers.NumPyEigensolver to conform to the new interfaces and result classes.

NumPyEigensolver Example

[Legacy]:

 
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)
[-1.41421356 -1.41421356]

[Updated]:

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)
[-1.41421356 -1.41421356]

Time Evolvers

The time evolvers were refactored in a new location. Instead of using a qiskit.utils.QuantumInstance, qiskit.algorithms.time_evolvers are now initialized using a 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

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
Note

In addition to taking in a qiskit.primitives.Estimator instance instead of a qiskit.utils.QuantumInstance, the new 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.

TrotterQRTE Example

[Legacy] Using QuantumInstance:

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)
CircuitStateFn(
    ┌─────────────────────┐
q:  ┤ exp(-it (X + Z))(1) ├
    └─────────────────────┘
)

[Updated] Using primitives:

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())
    ┌───────────┐┌───────────┐
q:  ┤ exp(it X) ├┤ exp(it Z) ├
    └───────────┘└───────────┘

Amplitude amplifiers

The amplitude amplifier algorithms were refactored in-place. Instead of a qiskit.utils.QuantumInstance, qiskit.algorithms.amplitude_amplifiers are now initialized using an instance of any Sampler primitive. That is, qiskit.primitives.Sampler.

Note

The full qiskit.algorithms.amplitude_amplifiers module has been refactored in place. Therefore, you don't need to change import paths.

Grover example

[Legacy] Using QuantumInstance:

 
from qiskit.algorithms import Grover
from qiskit.utils import QuantumInstance
 
qi = QuantumInstance(backend=backend)
grover = Grover(quantum_instance=qi)

[Updated] Using primitives:

from qiskit.algorithms import Grover
from qiskit.primitives import Sampler
 
grover = Grover(sampler=Sampler())

For complete code examples, see the following updated tutorials:


Amplitude estimators

Similarly to the amplitude amplifiers, the amplitude estimators were refactored in-place. Instead of a qiskit.utils.QuantumInstance, qiskit.algorithms.amplitude_estimators are now initialized using an instance of any Sampler primitive. That is, qiskit.primitives.Sampler.

Note

The full qiskit.algorithms.amplitude_estimators module has been refactored in place. You do not need to change import paths.

IAE example

[Legacy] Using QuantumInstance:

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:

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.


Phase estimators

The phase estimators were refactored in-place. Instead of a qiskit.utils.QuantumInstance, qiskit.algorithms.phase_estimators are now initialized by using an instance of any Sampler primitive. That is, qiskit.primitives.Sampler.

Note

The full qiskit.algorithms.phase_estimators module has been refactored in place. Therefore, you do not need to change import paths.

IPE example

[Legacy] Using QuantumInstance:

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:

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.