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:

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

    দৃষ্টি আকর্ষণ

    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)

  2. Algorithms refactored in-place (same namespace) to support both QuantumInstance and primitives. In the future, the use of QuantumInstance will be removed.

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

দৃষ্টি আকর্ষণ

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:

  1. For quick prototyping, you can use the reference implementations of primitives included in Qiskit: qiskit.primitives.Sampler and qiskit.primitives.Estimator.

  2. For finer algorithm tuning, a local simulator such as the primitive implementation in Aer: qiskit_aer.primitives.Sampler and qiskit_aer.primitives.Estimator.

  3. For executing in quantum hardware you can:

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:

  1. 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"})
    
  2. 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
    
    • 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.

দৃষ্টি আকর্ষণ

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:

নোট

In addition to taking in an Estimator instance instead of a QuantumInstance, the new VQE signature has undergone the following changes:

  1. The expectation and include_custom parameters have been removed, as this functionality is now defined at the Estimator level.

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

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

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

নোট

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.

VQE Example

[Legacy] Using Quantum Instance:

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 Quantum Instance:

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

নোট

In addition to taking in an Sampler instance instead of a QuantumInstance, the new QAOA signature has undergone the following changes:

  1. 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).

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

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

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

নোট

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.

QAOA Example

[Legacy] Using Quantum Instance:

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

NumPyMinimumEigensolver Example

[Legacy] Using Quantum Instance:

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

দৃষ্টি আকর্ষণ

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.

নোট

In addition to taking in an Estimator instance instead of a QuantumInstance, the new VQD signature has undergone the following changes:

  1. The expectation and include_custom parameters have been removed, as this functionality is now defined at the Estimator level.

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

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

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

নোট

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.

VQD Example

[Legacy] Using Quantum Instance:

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 in cloud simulator
service = QiskitRuntimeService(channel="ibm_quantum")
backend = service.backend("ibmq_qasm_simulator")

with Session(service=service, 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 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.

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#

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#

দৃষ্টি আকর্ষণ

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

নোট

In addition to taking in an Estimator instance instead of a QuantumInstance, the new VQD signature has undergone the following changes:

  1. The expectation parameter has been removed, as this functionality is now defined at the Estimator level.

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

TrotterQRTE Example

[Legacy] Using Quantum Instance:

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(run_options={"approximation": True, "shots": None})

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

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.

নোট

The full qiskit.algorithms.amplitude_amplifiers module has been refactored in place. No need to change import paths.

Grover Example

[Legacy] Using Quantum Instance:

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#

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.

নোট

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

IAE Example

[Legacy] Using Quantum Instance:

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

নোট

The full qiskit.algorithms.phase_estimators module has been refactored in place. No need to change import paths.

IPE Example

[Legacy] Using Quantum Instance:

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 complete code examples, see the following updated tutorials: