---
title: Qiskit v1.0 feature changes
description: Description of feature changes introduced in Qiskit v1.0 and how to update your code to work with them.
source: https://eu-de.quantum.cloud.ibm.com/docs/en/guides/qiskit-1.0-features
---

# Qiskit v1.0 feature changes

This guide describes migration paths for the most important feature changes in Qiskit v1.0, organized by module.
Use the table of contents on the right side to navigate to the module you are interested in.

## Qiskit v1.0 migration tool

To ease the migration process, you can use the
[`flake8-qiskit-migration`](https://github.com/qiskit-community/flake8-qiskit-migration)
tool to detect removed import paths in your code and suggest alternatives.

### Run with pipx

If you have [`pipx`](https://github.com/pypa/pipx) installed, simply run
the following command.

```sh
pipx run flake8-qiskit-migration <path-to-source-directory>
```

This will install the package to a temporary virtual environment and run
it on your code.

### Run with venv

If you don't want to use `pipx`, you can manually create a new
environment for the tool. This approach also lets you use
[`nbqa`](https://github.com/nbQA-dev/nbQA) to check code examples in
Jupyter notebooks. Delete the environment when you're finished.

```sh
# Make new environment and install
python -m venv .flake8-qiskit-migration-venv
source .flake8-qiskit-migration-venv/bin/activate
pip install flake8-qiskit-migration

# Run plugin on Python code
flake8 --select QKT100 <path-to-source-directory>  # e.g. `src/`

# (Optional) run plugin on notebooks
pip install nbqa
nbqa flake8 ./**/*.ipynb --select QKT100

# Deactivate and delete environment
deactivate
rm -r .flake8-qiskit-migration-venv
```

> **Limitations**
>
> This tool only detects removed import paths. It does not detect the use of removed
> methods (such as `QuantumCircuit.qasm`) or arguments. It also can't keep track
> of assignments such as `qk = qiskit`, although it can handle aliases such as
> `import qiskit as qk`.

For more information, see the [project's
repository](https://github.com/qiskit-community/flake8-qiskit-migration).

## Global instances and functions

### Aer

The `qiskit.Aer` object is not available in Qiskit v1.0. Instead, use the
same object from the `qiskit_aer` namespace, which is a drop-in replacement.
To install `qiskit_aer`, run:

```bash
pip install qiskit-aer
```

### BasicAer

The `qiskit.BasicAer` object is not available in Qiskit v1.0. See the
[`basicaer` migration section](#providers.basicaer) for
migration options.

### execute

The `qiskit.execute` function is not available in Qiskit v1.0. This
function served as a high-level wrapper around the
[`transpile`](/docs/api/qiskit/compiler#transpile) and
[`run`](/docs/api/qiskit/qiskit.providers.BackendV2#run) functions in Qiskit.
Instead of `qiskit.execute`, use the
[`transpile`](/docs/api/qiskit/compiler#transpile) function followed by
[`backend.run()`](/docs/api/qiskit/qiskit.providers.BackendV2#run).

```python
# Legacy path
from qiskit import execute

job = execute(circuit, backend)

# New path
from qiskit import transpile

new_circuit = transpile(circuit, backend)
job = backend.run(new_circuit)
```

Alternatively, the [Sampler](/docs/api/qiskit/1.4/qiskit.primitives.Sampler)
primitive is semantically equivalent to the removed `qiskit.execute`
function. The class
[`BackendSampler`](/docs/api/qiskit/1.4/qiskit.primitives.BackendSampler) is a
generic wrapper for backends that do not support primitives:

```python
from qiskit.primitives import BackendSampler

sampler = BackendSampler(backend)
job = sampler.run(circuit)
```

## qiskit.circuit

### QuantumCircuit.qasm

The `QuantumCircuit.qasm` method has been removed. Instead, use
[`qasm2.dump`](/docs/api/qiskit/qasm2#dump) or
[`qasm2.dumps`](/docs/api/qiskit/qasm2#dumps).

For Pygments-formatted output, look at the standalone
[`openqasm-pygments`](https://pypi.org/project/openqasm-pygments/) package,
as `qasm2.dump` and `qasm2.dumps` do not provide Pygments-colored output.

```python
from qiskit import QuantumCircuit

qc = QuantumCircuit(1)

# Old
qasm_str = qc.qasm()

# Alternative
from qiskit.qasm2 import dumps

qasm_str = dumps(qc)

# Alternative: Write to file
from qiskit.qasm2 import dump

with open("my_file.qasm", "w") as f:
    dump(qc, f)
```

### QuantumCircuit gates

The following gate methods have been removed in favor of more established
methods that append the same gates:

| Removed                  | Alternative                                                                        |
| ------------------------ | ---------------------------------------------------------------------------------- |
| `QuantumCircuit.cnot`    | [`QuantumCircuit.cx`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#cx)           |
| `QuantumCircuit.toffoli` | [`QuantumCircuit.ccx`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#ccx)         |
| `QuantumCircuit.fredkin` | [`QuantumCircuit.cswap`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#cswap)     |
| `QuantumCircuit.mct`     | [`QuantumCircuit.mcx`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#mcx)         |
| `QuantumCircuit.i`       | [`QuantumCircuit.id`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#id)           |
| `QuantumCircuit.squ`     | [`QuantumCircuit.unitary`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#unitary) |

The following circuit methods have been removed. Instead, these gates can be
applied to a circuit with `QuantumCircuit.append`.

| Removed                      | Alternative (append)                                                         |
| ---------------------------- | ---------------------------------------------------------------------------- |
| `QuantumCircuit.diagonal`    | [`DiagonalGate`](/docs/api/qiskit/qiskit.circuit.library.DiagonalGate)       |
| `QuantumCircuit.hamiltonian` | [`HamiltonianGate`](/docs/api/qiskit/qiskit.circuit.library.HamiltonianGate) |
| `QuantumCircuit.isometry`    | [`Isometry`](/docs/api/qiskit/qiskit.circuit.library.Isometry)               |
| `QuantumCircuit.iso`         | [`Isometry`](/docs/api/qiskit/qiskit.circuit.library.Isometry)               |
| `QuantumCircuit.uc`          | [`UCGate`](/docs/api/qiskit/qiskit.circuit.library.UCGate)                   |
| `QuantumCircuit.ucrx`        | [`UCRXGate`](/docs/api/qiskit/qiskit.circuit.library.UCRXGate)               |
| `QuantumCircuit.ucry`        | [`UCRYGate`](/docs/api/qiskit/qiskit.circuit.library.UCRYGate)               |
| `QuantumCircuit.ucrz`        | [`UCRZGate`](/docs/api/qiskit/qiskit.circuit.library.UCRZGate)               |

For example, for a [`DiagonalGate`](/docs/api/qiskit/qiskit.circuit.library.DiagonalGate):

```python
from qiskit.circuit import QuantumCircuit
# new location in the circuit library:
from qiskit.circuit.library import DiagonalGate  

circuit = QuantumCircuit(2)
circuit.h([0, 1])  # some initial state

gate = DiagonalGate([1, -1, -1, 1])
qubits = [0, 1]  # qubit indices on which to apply the gate
circuit.append(gate, qubits)  # apply the gate
```

The following `QuantumCircuit` methods have also been removed:

| Removed                          | Alternative                                                                                                     |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `QuantumCircuit.bind_parameters` | [`QuantumCircuit.assign_parameters`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#assign_parameters)          |
| `QuantumCircuit.snapshot`        | `qiskit-aer`'s [save instructions](https://qiskit.org/ecosystem/aer/apidocs/circuit.html#saving-simulator-data) |

## qiskit.converters

The `qiskit.converters.ast_to_dag` function has been removed from Qiskit. It converted the
abstract syntax tree generated by the legacy OpenQASM 2 parser to a
[`DAGCircuit`](/docs/api/qiskit/qiskit.dagcircuit.DAGCircuit). As the legacy
OpenQASM 2 parser has been removed (see [qiskit.qasm](#qiskit.qasm)), this
function no longer serves a purpose. Instead, parse your OpenQASM 2 files into
a `QuantumCircuit` using the
[`QuantumCircuit.from_qasm_file`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#from_qasm_file)
or
[`QuantumCircuit.from_qasm_str`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#from_qasm_str)
constructor methods (or the [`qiskit.qasm2`](/docs/api/qiskit/qasm2) module), then
convert that `QuantumCircuit` into a
[`DAGCircuit`](/docs/api/qiskit/qiskit.dagcircuit.DAGCircuit) with
[`circuit_to_dag`](/docs/api/qiskit/converters#circuit_to_dag).

```python
# Previous
from qiskit.converters import ast_to_dag
from qiskit.qasm import Qasm

dag = ast_to_dag(Qasm(filename="myfile.qasm").parse())

# Current alternative
import qiskit.qasm2
from qiskit.converters import circuit_to_dag

dag = circuit_to_dag(qiskit.qasm2.load("myfile.qasm"))
```

## qiskit.extensions

The `qiskit.extensions` module is no longer available. Most of its objects have been
integrated into the circuit library
([`qiskit.circuit.library`](/docs/api/qiskit/circuit_library)). To migrate to the
new location, simply replace `qiskit.extensions` with `qiskit.circuit.library`
in the object import path. This is a drop-in replacement.

```python
# Previous
from qiskit.extensions import DiagonalGate

# Current alternative
from qiskit.circuit.library import DiagonalGate
```

The classes moved to [`qiskit.circuit.library`](/docs/api/qiskit/circuit_library) are:

- [`DiagonalGate`](/docs/api/qiskit/qiskit.circuit.library.DiagonalGate)
- [`HamiltonianGate`](/docs/api/qiskit/qiskit.circuit.library.HamiltonianGate)
- [`Initialize`](/docs/api/qiskit/qiskit.circuit.library.Initialize)
- [`Isometry`](/docs/api/qiskit/qiskit.circuit.library.Isometry)
- `qiskit.circuit.library.generalized_gates.mcg_up_diag.MCGupDiag`
- [`UCGate`](/docs/api/qiskit/qiskit.circuit.library.UCGate)
- [`UCPauliRotGate`](/docs/api/qiskit/qiskit.circuit.library.UCPauliRotGate)
- [`UCRXGate`](/docs/api/qiskit/qiskit.circuit.library.UCRXGate)
- [`UCRYGate`](/docs/api/qiskit/qiskit.circuit.library.UCRYGate)
- [`UCRZGate`](/docs/api/qiskit/qiskit.circuit.library.UCRZGate)
- [`UnitaryGate`](/docs/api/qiskit/qiskit.circuit.library.UnitaryGate)

The following classes have been removed from the codebase, as their
functions were either redundant or linked to the `extensions` module:

| Removed              | Alternative                                                                                                         |
| -------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `SingleQubitUnitary` | [`qiskit.circuit.library.UnitaryGate`](/docs/api/qiskit/qiskit.circuit.library.UnitaryGate)                         |
| `Snapshot`           | Use `qiskit-aer`'s [save instructions](https://qiskit.org/ecosystem/aer/apidocs/circuit.html#saving-simulator-data) |
| `ExtensionError`     | A relevant error class                                                                                              |

## qiskit.primitives

The most notable change in the [`qiskit.primitives`](/docs/api/qiskit/primitives) module is the
introduction of the new **primitives V2 interface**. This section shows how to migrate your
workflow from primitives V1 to primitives V2, as well as the few changes that have taken place
in the inputs accepted by the V1 interface.

> **Note**
>
> Starting with the v1.0 release, we will refer to the pre-1.0 primitives interface as "primitives V1".

### Migrate from V1 to V2

The formal distinction between the primitives V1 and V2 APIs are the base classes from which
primitives implementations inherit. To transition to the new base classes, you can maintain
the original import path from `qiskit.primitives`:

| Migrate from    | Replace with                                                            |
| --------------- | ----------------------------------------------------------------------- |
| `BaseEstimator` | [`BaseEstimatorV2`](/docs/api/qiskit/qiskit.primitives.BaseEstimatorV2) |
| `BaseSampler`   | [`BaseSamplerV2`](/docs/api/qiskit/qiskit.primitives.BaseSamplerV2)     |

The names of the qiskit core implementations of the V2 primitives (those importable from `qiskit.primitives`),
have been modified to clarify their purpose as implementations that can be run locally
with a statevector simulator backend. The new names **do not include the -V2 suffix**.

| Migrate from                  | Replace with                                                                                        |
| ----------------------------- | --------------------------------------------------------------------------------------------------- |
| `qiskit.primitives.Estimator` | [`qiskit.primitives.StatevectorEstimator`](/docs/api/qiskit/qiskit.primitives.StatevectorEstimator) |
| `qiskit.primitives.Sampler`   | [`qiskit.primitives.StatevectorSampler`](/docs/api/qiskit/qiskit.primitives.StatevectorSampler)     |

There are some conceptual differences to think about when migrating from V1 to V2.
These differences are dictated by the base class, but are shown in the following examples using the statevector
implementations found in `qiskit.primitives`:

> **Note**
>
> For the following examples, assume the following imports and primitive initializations:
>
> ```python
> from qiskit.primitives import (
>     Sampler,
>     StatevectorSampler,
>     Estimator,
>     StatevectorEstimator,
> )
>
> estimator_v1 = Estimator()
> sampler_v1 = Sampler()
> estimator_v2 = StatevectorEstimator()
> sampler_v2 = StatevectorSampler()
>
> # define circuits, observables and parameter values
> ```

1. `Sampler and Estimator`: The new V2 primitives are designed to accept **vectorized inputs**, where single circuits can be grouped with array-valued specifications. That is, one circuit can be executed
   for arrays of `n` parameter sets, `n` observables, or both (in the case of Estimator). Each group is called a **primitive unified bloc (pub)**, and can be represented as a tuple: `(1 x circuit, [n x observables], [n x parameters])`. The V1 interface didn't allow for the same flexibility.  Instead, the number of input circuits had to match the number of observables and
   parameter sets, as shown in the following examples (select a tab to see each example):

### Estimator, 1 circuit, 4 observables

```python
# executing 1 circuit with 4 observables using Estimator V1
job = estimator_v1.run([circuit] * 4, [obs1, obs2, obs3, obs4])
evs = job.result().values

# executing 1 circuit with 4 observables using Estimator V2
job = estimator_v2.run([(circuit, [obs1, obs2, obs3, obs4])])
evs = job.result()[0].data.evs
```

### Sampler, 1 circuit, 3 parameter sets

```python
# executing 1 circuit with 3 parameter sets using Sampler V1
job = sampler_v1.run([circuit] * 3, [vals1, vals2, vals3])
dists = job.result().quasi_dists

# executing 1 circuit with 3 parameter sets using Sampler V2
job = sampler_v2.run([(circuit, [vals1, vals2, vals3])])
counts = job.result()[0].data.meas.get_counts()
```

### Estimator, 1 circuit, 4 observables, 2 parameter sets

```python
# executing 1 circuit with 4 observables and 2 parameter sets using Estimator V1
job = estimator_v1.run([circuit] * 8, [obs1, obs2, obs3, obs4] * 2, [vals1, vals2] * 4)
evs = job.result().values

# executing 1 circuit with 4 observables and 2 parameter sets using Estimator V2
job = estimator_v2.run([(circuit, [[obs1, obs2, obs3, obs4]], [[vals1], [vals2]])])
evs = job.result()[0].data.evs
```

V2 primitives accept multiple PUBs as inputs, and each pub gets its own result. This
lets you run different circuits with various parameter/observable combinations,
which was not always possible in the V1 interface:

### Sampler, 2 circuits, 1 parameter set

```python
# executing 2 circuits with 1 parameter set using Sampler V1
job = sampler_v1.run([circuit1, circuit2], [vals1] * 2)
dists = job.result().quasi_dists

# executing 2 circuits with 1 parameter set using Sampler V2
job = sampler_v2.run([(circuit1, vals1), (circuit2, vals1)])
counts1 = job.result()[0].data.meas.get_counts()  # result for pub 1 (circuit 1)
counts2 = job.result()[1].data.meas.get_counts()  # result for pub 2 (circuit 2)
```

### Estimator, 2 circuits, 2 different observables

```python
# executing 2 circuits with 2 different observables using Estimator V1
job = estimator_v1.run([circuit1, circuit2] , [obs1, obs2])
evs = job.result().values

# executing 2 circuits with 2 different observables using Estimator V2
job = estimator_v2.run([(circuit1, obs1), (circuit2, obs2)])
evs1 = job.result()[0].data.evs  # result for pub 1 (circuit 1)
evs2 = job.result()[1].data.evs  # result for pub 2 (circuit 2)
```

2. [Sampler](/docs/api/qiskit/qiskit.primitives.BaseSamplerV2): The V2 sampler now
   returns measurement outcome samples in the form of **bitstrings** or
   **counts**, instead of the quasi-probability distributions from the V1
   interface. The bitstrings show the measurement outcomes, preserving the shot
   order in which they were measured. The V2 Sampler result objects organize
   data in terms of their input circuits' classical register names, for
   compatibility with dynamic circuits.

   ```python
   # Define quantum circuit with 2 qubits
   circuit = QuantumCircuit(2)
   circuit.h(0)
   circuit.cx(0, 1)
   circuit.measure_all()
   circuit.draw()
   ```

   ```text
           ┌───┐      ░ ┌─┐
      q_0: ┤ H ├──■───░─┤M├───
           └───┘┌─┴─┐ ░ └╥┘┌─┐
      q_1: ─────┤ X ├─░──╫─┤M├
                └───┘ ░  ║ └╥┘
   meas: 2/══════════════╩══╩═
                         0  1
   ```

   > **Default classical register name**
   >
   > In the circuit above, notice that the name of the classical register defaults to `"meas"`.
   > This name will be used later to access the measurement bitstrings.

   ```python
   # Run using V1 Sampler
   result = sampler_v1.run(circuit).result()
   quasi_dist = result.quasi_dists[0]
   print(f"The quasi-probability distribution is: {quasi_dist}")
   ```

   ```text
   The quasi-probability distribution is: {0: 0.5, 3: 0.5}
   ```

   ```python
   # Run using V2 Sampler
   result = sampler_v2.run([circuit]).result()
   # Access result data for pub 0
   data_pub = result[0].data
   # Access bitstrings for the classical register "meas"
   bitstrings = data_pub.meas.get_bitstrings()
   print(f"The number of bitstrings is: {len(bitstrings)}")
   # Get counts for the classical register "meas"
   counts = data_pub.meas.get_counts()
   print(f"The counts are: {counts}")
   ```

   ```text
   The number of bitstrings is: 1024
   The counts are: {'00': 523, '11': 501}
   ```

3. `Sampler and Estimator`: The sampling overhead, commonly exposed by V1 implementations
   through the `shots` run option, is now an argument of the primitives `run()` method
   that can be specified at the **PUB** level.
   The V2 base classes expose the arguments in formats different from the V1 API:

   - [`BaseSamplerV2.run`](/docs/api/qiskit/qiskit.primitives.BaseSamplerV2#run)
     exposes a `shots` argument (similar to the previous workflow):
     ```python
     # Sample two circuits at 128 shots each.
     sampler_v2.run([circuit1, circuit2], shots=128)
     # Sample two circuits at different amounts of shots. 
     # The "None"s are necessary as placeholders
     # for the lack of parameter values in this example.
     sampler_v2.run([(circuit1, None, 123), (circuit2, None, 456)])
     ```

   - [`EstimatorV2.run`](/docs/api/qiskit/qiskit.primitives.BaseEstimatorV2#run)
     introduces a `precision` argument that specifies the error bars that the
     primitive implementation should target for expectation values estimates:
     ```python
     # Estimate expectation values for two PUBs, both with 0.05 precision.
     estimator_v2.run([(circuit1, obs_array1), 
       (circuit2, obs_array_2)], precision=0.05
       )
     ```

### Updates in the V1 interface

- Implicit conversion from a dense `BaseOperator` to a
  [`SparsePauliOp`](/docs/api/qiskit/qiskit.quantum_info.SparsePauliOp) in
  [`Estimator`](/docs/api/qiskit/1.4/qiskit.primitives.Estimator) observable arguments
  is no longer allowed. You should explicitly convert to a `SparsePauliOp`
  by using
  [`SparsePauliOp.from_operator(operator)`](/docs/api/qiskit/qiskit.quantum_info.SparsePauliOp#from_operator)
  instead.

- Using a [`PauliList`](/docs/api/qiskit/qiskit.quantum_info.PauliList) in
  Estimator observable arguments is no longer allowed. Instead you should
  explicitly convert the argument by using
  [`SparsePauliOp(pauli_list)`](/docs/api/qiskit/qiskit.quantum_info.SparsePauliOp)
  first.

## qiskit.providers

### basicaer

Most of the functionality in the `qiskit.providers.basicaer` module has been
replaced with the new
[`qiskit.providers.basic_provider`](/docs/api/qiskit/providers_basic_provider)
module, except for the `UnitarySimulatorPy` and `StatevectorSimulatorPy`
classes, which have been removed; their functionality was already contained in
the [`quantum_info`](/docs/api/qiskit/quantum_info) module.

The migration to the new paths is straightforward. You can replace most
classes in `qiskit.providers.basicaer` with their
[`qiskit.providers.basic_provider`](/docs/api/qiskit/providers_basic_provider)
counterpart (drop-in replacement). Note that the following classes have
new paths and names:

| Removed                     | Alternative                                                                             |
| --------------------------- | --------------------------------------------------------------------------------------- |
| `qiskit.providers.basicaer` | [`qiskit.providers.basic_provider`](/docs/api/qiskit/providers_basic_provider)          |
| `BasicAerProvider`          | [`BasicProvider`](/docs/api/qiskit/qiskit.providers.basic_provider.BasicProvider)       |
| `BasicAerJob`               | [`BasicProviderJob`](/docs/api/qiskit/qiskit.providers.basic_provider.BasicProviderJob) |
| `QasmSimulatorPy`           | [`BasicSimulator`](/docs/api/qiskit/qiskit.providers.basic_provider.BasicSimulator)     |

> **Global instances**
>
> Be aware of any global instances when migrating to the new module. There is no replacement for
> the `BasicAer` global instance that could be directly imported as `qiskit.BasicAer`. This means that
> `from qiskit import BasicProvider` is no longer a valid import.
> Instead, the provider class must be imported from its submodule and instantiated by the user:
>
> ```python
> # Previous
> from qiskit import BasicAer
> backend = BasicAer.get_backend("backend_name")
>
> # Current
> from qiskit.providers.basic_provider import BasicProvider
> backend = BasicProvider().get_backend("backend_name")
> ```

The unitary and statevector simulators can be replaced with
different [`quantum_info`](/docs/api/qiskit/quantum_info) classes. This is not a
drop-in replacement, but the changes are minimal. See the following migration
examples:

| Removed                  | Alternative                                                                    |
| ------------------------ | ------------------------------------------------------------------------------ |
| `UnitarySimulatorPy`     | [`quantum_info.Operator`](/docs/api/qiskit/qiskit.quantum_info.Operator)       |
| `StatevectorSimulatorPy` | [`quantum_info.Statevector`](/docs/api/qiskit/qiskit.quantum_info.Statevector) |

The following examples show the migration paths of the `basicaer` simulators.

### Statevector simulator

```python
from qiskit import QuantumCircuit

qc = QuantumCircuit(3)
qc.h(0)
qc.h(1)
qc.cx(1, 2)
qc.measure_all()

# Previous
from qiskit import BasicAer
backend = BasicAer.get_backend("statevector_simulator")
statevector = backend.run(qc).result().get_statevector()

# Current
qc.remove_final_measurements()  # no measurements allowed
from qiskit.quantum_info import Statevector
statevector = Statevector(qc)
```

### Unitary simulator

```python
from qiskit import QuantumCircuit
qc = QuantumCircuit(3)
qc.h(0)
qc.h(1)
qc.cx(1, 2)
qc.measure_all()

# Previous
from qiskit import BasicAer
backend = BasicAer.get_backend("unitary_simulator")
result = backend.run(qc).result()

# Current
qc.remove_final_measurements()  # no measurements allowed
from qiskit.quantum_info import Operator
result = Operator(qc).data
```

### QASM simulator

```python
from qiskit import QuantumCircuit
qc = QuantumCircuit(3)
qc.h(0)
qc.h(1)
qc.cx(1, 2)
qc.measure_all()

# Previous
from qiskit import BasicAer
backend = BasicAer.get_backend("qasm_simulator")
result = backend.run(qc).result()

# One current option
from qiskit.providers.basic_provider import BasicProvider
backend = BasicProvider().get_backend("basic_simulator")
result = backend.run(qc).result()

# Another current option is to specify it directly
from qiskit.providers.basic_provider import BasicSimulator
backend = BasicSimulator()
result = backend.run(qc).result()
```

### fake\_provider

Most of the user-facing
`qiskit.providers.fake_provider` components have
been migrated to the `qiskit-ibm-runtime` Python package. This includes the
fake provider classes, all of the device-specific fake backends (such as
`FakeVigo`, `FakeNairobiV2`, and `FakeSherbrooke`), and the fake backend
base classes. Click through the following tabs to see the affected classes.

### Fake Backends

- Any class in `qiskit.providers.fake_provider.backends`
- `fake_provider.fake_backend.FakeBackend`
- `fake_provider.fake_backend.FakeBackendV2`

### Fake Providers

- `fake_provider.FakeProvider`
- `fake_provider.FakeProviderForBackendV2`
- `fake_provider.FakeProviderFactory`

To migrate to the new path:

1. Install `qiskit-ibm-runtime` `0.17.1` or later:

   ```bash
   pip install 'qiskit-ibm-runtime>=0.17.1'
   ```

2. Replace instances of `qiskit.providers.fake_provider` in your code with
   `qiskit_ibm_runtime.fake_provider`. For example:

   ```python
   # Old
   from qiskit.providers.fake_provider import FakeProvider
   backend1 = FakeProvider().get_backend("fake_ourense")

   from qiskit.providers.fake_provider import FakeSherbrooke
   backend2 = FakeSherbrooke()

   # Alternative
   from qiskit_ibm_runtime.fake_provider import FakeProvider
   backend1 = FakeProvider().get_backend("fake_ourense")

   from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
   backend2 = FakeSherbrooke()
   ```

The fake backend base classes have also been migrated, but have some differences in the import path:

| Removed                                           | Alternative                                                            |
| ------------------------------------------------- | ---------------------------------------------------------------------- |
| `qiskit.providers.fake_provider.FakeQasmBackend`  | `qiskit_ibm_runtime.fake_provider.fake_qasm_backend.FakeQasmBackend`   |
| `qiskit.providers.fake_provider.FakePulseBackend` | `qiskit_ibm_runtime.fake_provider.fake_pulse_backend.FakePulseBackend` |

> **Note**
>
> If you depend on fake backends for unit testing a downstream library and have conflicts with the
> `qiskit-ibm-runtime` dependency, you can also find new Qiskit-native generic fake backend alternatives.
> These include the following `BackendV1` classes (drop-in replacements):
>
> - [`qiskit.providers.fake_provider.Fake5QV1`](/docs/api/qiskit/1.4/qiskit.providers.fake_provider.Fake5QV1)
> - [`qiskit.providers.fake_provider.Fake20QV1`](/docs/api/qiskit/1.4/qiskit.providers.fake_provider.Fake20QV1)
> - [`qiskit.providers.fake_provider.Fake7QPulseV1`](/docs/api/qiskit/1.4/qiskit.providers.fake_provider.Fake7QPulseV1)
> - [`qiskit.providers.fake_provider.Fake27QPulseV1`](/docs/api/qiskit/1.4/qiskit.providers.fake_provider.Fake27QPulseV1)
> - [`qiskit.providers.fake_provider.Fake127QPulseV1`](/docs/api/qiskit/1.4/qiskit.providers.fake_provider.Fake127QPulseV1)
>
> This is a configurable class that returns `BackendV2` instances:
>
> - [`qiskit.providers.fake_provider.GenericBackendV2`](/docs/api/qiskit/qiskit.providers.fake_provider.GenericBackendV2)

### fake\_provider (special testing backends)

The fake backend classes for special testing purposes in
`qiskit.providers.fake_provider` have
**not** been migrated to `qiskit_ibm_runtime.fake_provider`. The recommended
migration path is to use the new
[`GenericBackendV2`](/docs/api/qiskit/qiskit.providers.fake_provider.GenericBackendV2)
class to configure a backend with similar properties or to build a custom
target.

| Removed                                       | Alternative                                                                                          |
| --------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `fake_provider.FakeBackendV2`                 | [`fake_provider.GenericBackendV2`](/docs/api/qiskit/qiskit.providers.fake_provider.GenericBackendV2) |
| `fake_provider.FakeBackend5QV2`               | [`fake_provider.GenericBackendV2`](/docs/api/qiskit/qiskit.providers.fake_provider.GenericBackendV2) |
| `fake_provider.FakeBackendV2LegacyQubitProps` | [`fake_provider.GenericBackendV2`](/docs/api/qiskit/qiskit.providers.fake_provider.GenericBackendV2) |
| `fake_provider.FakeBackendSimple`             | [`fake_provider.GenericBackendV2`](/docs/api/qiskit/qiskit.providers.fake_provider.GenericBackendV2) |
| `fake_provider.ConfigurableFakeBackend`       | [`fake_provider.GenericBackendV2`](/docs/api/qiskit/qiskit.providers.fake_provider.GenericBackendV2) |

Example: Migrate to the new
[`GenericBackendV2`](/docs/api/qiskit/qiskit.providers.fake_provider.GenericBackendV2)
class:

```python
# Legacy path
from qiskit.providers.fake_provider import FakeBackend5QV2
backend = FakeBackend5QV2()

# New path
from qiskit.providers.fake_provider import GenericBackendV2
backend = GenericBackendV2(num_qubits=5)

# Note that this class generates a 5q backend with generic
# properties that serves the same purpose as FakeBackend5QV2
# but will not be identical.
```

### Other migration tips

- Importing from `qiskit.providers.aer` is no longer possible. Instead, import
  from `qiskit_aer`, which is a drop-in replacement. To install `qiskit_aer`,
  run:

  ```bash
  pip install qiskit-aer
  ```

- Support for running pulse jobs on backends from
  [`qiskit.providers.fake_provider`](/docs/api/qiskit/providers_fake_provider) has
  been removed in Qiskit v1.0.  This is because Qiskit Aer removed its
  simulation functionality for such jobs.  For low-level Hamiltonian-simulation
  workloads, consider using a specialized library such as [Qiskit
  Dynamics](https://qiskit-extensions.github.io/qiskit-dynamics/).

## qiskit.pulse

### ParametricPulse

The `qiskit.pulse.library.parametric_pulses.ParametricPulse` base class and
pulse library have been superseded by
[`qiskit.pulse.SymbolicPulse`](/docs/api/qiskit/1.4/qiskit.pulse.library.SymbolicPulse)
and the corresponding pulse library. `SymbolicPulse` supports
[QPY](/docs/api/qiskit/qpy) serialization:

```python
from qiskit import pulse, qpy

with pulse.build() as schedule:
    pulse.play(pulse.Gaussian(100, 0.1, 25), pulse.DriveChannel(0))

with open('schedule.qpy', 'wb') as fd:
    qpy.dump(schedule, fd)
```

| Removed                                                 | Alternative                                                                                                |
| ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `pulse.library.parametric_pulses.ParametricPulse`       | [`qiskit.pulse.SymbolicPulse`](/docs/api/qiskit/1.4/qiskit.pulse.library.SymbolicPulse)                    |
| `pulse.library.parametric_pulses.Constant`              | [`pulse.library.symbolic_pulses.Constant`](/docs/api/qiskit/1.4/qiskit.pulse.library.Constant)             |
| `pulse.library.parametric_pulses.Drag`                  | [`pulse.library.symbolic_pulses.Drag`](/docs/api/qiskit/1.4/qiskit.pulse.library.Drag)                     |
| `pulse.library.parametric_pulses.Gaussian`              | [`pulse.library.symbolic_pulses.Gaussian`](/docs/api/qiskit/1.4/qiskit.pulse.library.Gaussian)             |
| `qiskit.pulse.library.parametric_pulses.GaussianSquare` | [`pulse.library.symbolic_pulses.GaussianSquare`](/docs/api/qiskit/1.4/qiskit.pulse.library.GaussianSquare) |

### Complex-valued amplitude

Complex-valued pulse amplitude (`amp`) is replaced by an (`amp`,
`angle`) duo. This representation is more intuitive, especially for some
calibration tasks such as angle calibration:

```python
from qiskit import pulse
from qiskit.circuit import Parameter
from math import pi

with pulse.build() as schedule:
    angle = Parameter("θ")
    pulse.play(pulse.Gaussian(100, 0.1, 25, angle=angle), pulse.DriveChannel(0))
schedule.assign_parameters({angle: pi})
```

### Injecting circuit gate operations

Injecting circuit gate operations into the pulse builder context through
[`qiskit.pulse.builder.call`](/docs/api/qiskit/1.4/pulse#call) is no longer possible.
This removal affects input arguments of type `QuantumCircuit`, as well as the
following functions:

- `qiskit.pulse.builder.call_gate`
- `qiskit.pulse.builder.cx`
- `qiskit.pulse.builder.u1`
- `qiskit.pulse.builder.u2`
- `qiskit.pulse.builder.u3`
- `qiskit.pulse.builder.x`

If you still want to inject backend-calibrated schedules, use the following
pattern instead of calling gate commands.

```python
from qiskit.providers.fake_provider import GenericBackendV2
from qiskit import pulse

backend = GenericBackendV2(num_qubits=5)
sched = backend.target["x"][(qubit,)].calibration

with pulse.build() as only_pulse_scheds:
    pulse.call(sched)
```

Similarly, a [`QuantumCircuit`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit) can
be injected in the builder context by manually transpiling and scheduling the
object.

```python
from math import pi
from qiskit.compiler import schedule, transpile

qc = QuantumCircuit(2)
qc.rz(pi / 2, 0)
qc.sx(0)
qc.rz(pi / 2, 0)
qc.cx(0, 1)
qc_t = transpile(qc, backend)
sched = schedule(qc_t, backend)
with pulse.build() as only_pulse_scheds:
    pulse.call(sched)
```

We recommend writing a minimum pulse program with the builder and attaching it to
`QuantumCircuit` through the
[`QuantumCircuit.add_calibration`](/docs/api/qiskit/1.4/qiskit.circuit.QuantumCircuit#add_calibration)
method as a microcode of a gate instruction, rather than writing the entire
program with the pulse model.

### builder.build

The following arguments in `qiskit.pulse.builder.build` have been removed with
no alternative.

- `default_transpiler_settings`
- `default_circuit_scheduler_settings`

These functions have also been removed:

- `qiskit.pulse.builder.active_transpiler_settings`
- `qiskit.pulse.builder.active_circuit_scheduler_settings`
- `qiskit.pulse.builder.transpiler_settings`
- `qiskit.pulse.builder.circuit_scheduler_settings`

This is because it's no longer possible to inject circuit objects into the
builder context (see [Injecting circuit gate
operations](#injecting-circuit-gate-operations)); these settings were for
converting injected objects into pulse representations.

### library

The discrete pulse library has been removed from the code base. This includes:

- `qiskit.pulse.library.constant`
- `qiskit.pulse.library.zero`
- `qiskit.pulse.library.square`
- `qiskit.pulse.library.sawtooth`
- `qiskit.pulse.library.triangle`
- `qiskit.pulse.library.cos`
- `qiskit.pulse.library.sin`
- `qiskit.pulse.library.gaussian`
- `qiskit.pulse.library.gaussian_deriv`
- `qiskit.pulse.library.sech`
- `qiskit.pulse.library.sech_deriv`
- `qiskit.pulse.library.gaussian_square`
- `qiskit.pulse.library.drag`

Instead, use the corresponding
[`qiskit.pulse.SymbolicPulse`](/docs/api/qiskit/1.4/qiskit.pulse.library.SymbolicPulse),
with
[`SymbolicPulse.get_waveform()`](/docs/api/qiskit/1.4/qiskit.pulse.library.SymbolicPulse#get_waveform).
For example, instead of `pulse.gaussian(100,0.5,10)`, use
`pulse.Gaussian(100,0.5,10).get_waveform()`. Note that the phase of both
[`Sawtooth`](/docs/api/qiskit/1.4/qiskit.pulse.library.Sawtooth) and
[`Square`](/docs/api/qiskit/1.4/qiskit.pulse.library.Square) is defined such
that a phase of `2\\pi` shifts by a full cycle, contrary to the discrete
counterpart. Also note that complex amplitudes are no longer supported in
the symbolic pulse library; use `float`, `amp`, and  `angle` instead.

### ScalableSymbolicPulse

It is no longer possible to load library `qiskit.pulse.ScalableSymbolicPulse`
objects with a complex `amp` parameter from version 5 or earlier qpy files
(Qiskit Terra \< 0.23.0). No migration action is required, as complex `amp` will
automatically be converted to `float` (`amp`, `angle`).

This change applies to these pulses:

- [`qiskit.pulse.Constant`](/docs/api/qiskit/1.4/qiskit.pulse.library.Constant)
- [`qiskit.pulse.Drag`](/docs/api/qiskit/1.4/qiskit.pulse.library.Drag)
- [`qiskit.pulse.Gaussian`](/docs/api/qiskit/1.4/qiskit.pulse.library.Gaussian)
- [`qiskit.pulse.GaussianSquare`](/docs/api/qiskit/1.4/qiskit.pulse.library.GaussianSquare)

## qiskit.qasm

The legacy OpenQASM 2 parser module previously in `qiskit.qasm` has
been superseded by the [`qiskit.qasm2`](/docs/api/qiskit/qasm2) module, which
provides a faster and more accurate parser for OpenQASM 2. The high level
`QuantumCircuit` methods
[`from_qasm_file()`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#from_qasm_file)
and
[`from_qasm_str()`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#from_qasm_str)
remain the same, but will use the new parser internally. However, the public
interface for the `qasm2` module is not the same. While the `qiskit.qasm`
module provided an interface to an abstract syntax tree returned by the `ply`
parser library, `qiskit.qasm2` does not expose the AST or any lower level
implementation details about the parser. It instead takes OpenQASM 2 input and
outputs a [`QuantumCircuit`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit) object.

For example, if you were previously running something like this:

```python
import qiskit.qasm
from qiskit.converters import ast_to_dag, dag_to_circuit

ast = qiskit.qasm.Qasm(filename="myfile.qasm").parse()
dag = ast_to_dag(ast)
qasm_circ = dag_to_circuit(dag)
```

Replace it with the following:

```python
import qiskit.qasm2

qasm_circ = qiskit.qasm2.load("myfile.qasm")
```

## qiskit.quantum\_info

The `qiskit.quantum_info.synthesis` module has been migrated to various
locations in the codebase, mostly [`qiskit.synthesis`](/docs/api/qiskit/synthesis).

| Removed                    | Alternative                                                                                                                    |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `OneQubitEulerDecomposer`  | [`qiskit.synthesis.one_qubit.OneQubitEulerDecomposer`](/docs/api/qiskit/qiskit.synthesis.OneQubitEulerDecomposer)              |
| `TwoQubitBasisDecomposer`  | [`qiskit.synthesis.two_qubits.TwoQubitBasisDecomposer`](/docs/api/qiskit/qiskit.synthesis.TwoQubitBasisDecomposer)             |
| `XXDecomposer`             | [`qiskit.synthesis.two_qubits.XXDecomposer`](/docs/api/qiskit/qiskit.synthesis.XXDecomposer)                                   |
| `two_qubit_cnot_decompose` | [`qiskit.synthesis.two_qubits.two_qubit_cnot_decompose`](/docs/api/qiskit/synthesis#qiskit.synthesis.two_qubit_cnot_decompose) |
| `Quaternion`               | [`qiskit.quantum_info.Quaternion`](/docs/api/qiskit/qiskit.quantum_info.Quaternion)                                            |

This move has not affected the usual import path of `Quaternion`, but you can no longer access
it through `qiskit.quantum_info.synthesis`.

Finally, `cnot_rxx_decompose` has been removed.

## qiskit.test

The `qiskit.test` module is no longer a public module.  This was never intended to be public,
nor to be used outside of the  Qiskit test suite.  All functionality was specific to Qiskit and no
alternative is provided; if you needed similar functionality, you should include it in your own
test harnesses.

## qiskit.tools

The `qiskit.tools` module was removed in Qiskit v1.0. Most of this functionality was
either replaced by similar functionality in other packages or removed with no alternative.
The primary exception is the `qiskit.tools.parallel_map()` function, which has been relocated to
the [`qiskit.utils`](/docs/api/qiskit/utils#parallel_map) module. It can be used
from this new location instead. For example:

If you were previously running:

```python
# Previous
from qiskit.tools import parallel_map

parallel_map(func, input)

# Current
from qiskit.utils import parallel_map

parallel_map(func, input)
```

### jupyter

The `qiskit.tools.jupyter` submodule has been removed because the functionality
in this module is tied to the legacy `qiskit-ibmq-provider` package, which is no
longer supported. It also only supported `BackendV1` and not the newer
[`BackendV2`](/docs/api/qiskit/qiskit.providers.BackendV2) interface.

### monitor

The `qiskit.tools.monitor` submodule has been removed as it was tied to the
legacy `qiskit-ibmq-provider` package, which is no longer supported (it also
only supported `BackendV1` interface and not the newer
[`BackendV2`](/docs/api/qiskit/qiskit.providers.BackendV2) interface). There is
no alternative provided for this functionality.

### visualization

The `qiskit.tools.visualization` submodule has been removed. This module was a
legacy redirect from the original location of the Qiskit visualization module and
was moved to [`qiskit.visualization`](/docs/api/qiskit/visualization) in Qiskit
0.8.0. If you're still using this path, update your imports from
`qiskit.tools.visualization` to
[`qiskit.visualization`](/docs/api/qiskit/visualization).

```python
# Previous
from qiskit.tools.visualization import plot_histogram

plot_histogram(counts)

# Current
from qiskit.visualization import plot_histogram

plot_histogram(counts)
```

### events

The `qiskit.tools.events` module and the `progressbar()` utility it exposed
have been removed. This module's functionality was not widely used and is
better covered by dedicated packages such as
[tqdm](https://github.com/tqdm/tqdm).

## qiskit.transpiler

### synthesis

The items in `qiskit.transpiler.synthesis` module have been migrated to new locations:

| Removed                                                                                                                                                  | Alternative                                                                                          |
| -------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `qiskit.transpiler.synthesis.aqc` (except for [`AQCSynthesisPlugin`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.aqc_plugin.AQCSynthesisPlugin)) | [`qiskit.synthesis.unitary.aqc`](/docs/api/qiskit/qiskit.synthesis.unitary.aqc)                      |
| `qiskit.transpiler.synthesis.graysynth`                                                                                                                  | [`qiskit.synthesis.synth_cnot_phase_aam`](/docs/api/qiskit/synthesis#synth_cnot_phase_aam)           |
| `qiskit.transpiler.synthesis.cnot_synth`                                                                                                                 | [`qiskit.synthesis.synth_cnot_count_full_pmh`](/docs/api/qiskit/synthesis#synth_cnot_count_full_pmh) |

### passes

The `NoiseAdaptiveLayout` transpiler pass has been superseded by
[`VF2Layout`](/docs/api/qiskit/qiskit.transpiler.passes.VF2Layout) and
[`VF2PostLayout`](/docs/api/qiskit/qiskit.transpiler.passes.VF2PostLayout),
which set a layout based on the reported noise characteristics of a
backend. Both the pass and the corresponding `"noise_adaptive"` layout stage
plugin have been removed from Qiskit.

The `CrosstalkAdaptiveSchedule` transpiler pass has been removed from the
code base. This pass was no longer usable because its internal operation
was dependent on custom properties being set in the `BackendProperties` payload
of a `BackendV1` instance. As no backends are setting these fields, the pass has
been removed.

### passmanager

The `append` methods of the
[`ConditionalController`](/docs/api/qiskit/qiskit.passmanager.ConditionalController),
[`FlowControllerLinear`](/docs/api/qiskit/qiskit.passmanager.FlowControllerLinear), and
[`DoWhileController`](/docs/api/qiskit/qiskit.passmanager.DoWhileController) classes
have been removed. Instead, all tasks must be provided when the controller
objects are constructed.

## qiskit.utils

The following tools in `qiskit.utils` have been removed with no replacement:

- `qiskit.utils.arithmetic`
- `qiskit.utils.circuit_utils`
- `qiskit.utils.entangler_map`
- `qiskit.utils.name_unnamed_args`

These functions were used exclusively in the `qiskit.algorithms` and
`qiskit.opflow` modules, which have also been removed.

## qiskit.visualization

The `qiskit.visualization.qcstyle` module has been removed. Use
`qiskit.visualization.circuit.qcstyle` as direct replacement.
