Skip to content

Commit

Permalink
Remove deprecated BackendV1 elements, including base class, `provid…
Browse files Browse the repository at this point in the history
…ers.models` and `qobj` modules (#13793)

* Remove BackendV1, converters, models, qobj and update tests.

* Add reno

* Update releasenotes/notes/remove-backend-v1-et-al-cccd8f6b71a97ffc.yaml

Co-authored-by: Eli Arbel <46826214+eliarbel@users.noreply.github.com>

* Include qobj_id removal in reno. Modify result args to kwargs as specified in 1.4 deprecation warning.

* Update __init__.py

* Remove unused import

* Remove remaining qobj references (including test names and comments). Remove json decoding utils that weren't part of the public API and flew under the radar in the Fake Backend removal PR.

* Document migration of MeasLevel and MeasReturnType

* Mix malformed table

* Apply comments from Matt's review

---------

Co-authored-by: Eli Arbel <46826214+eliarbel@users.noreply.github.com>
Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
  • Loading branch information
3 people authored Mar 5, 2025
1 parent 9e455f2 commit 9c00a93
Show file tree
Hide file tree
Showing 53 changed files with 286 additions and 7,718 deletions.
2 changes: 0 additions & 2 deletions docs/apidoc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ Primitives and providers:
providers
providers_basic_provider
providers_fake_provider
providers_models

Results and visualizations:

Expand Down Expand Up @@ -83,5 +82,4 @@ Other:

compiler
exceptions
qobj
utils
6 changes: 0 additions & 6 deletions docs/apidoc/providers_models.rst

This file was deleted.

6 changes: 0 additions & 6 deletions docs/apidoc/qobj.rst

This file was deleted.

50 changes: 12 additions & 38 deletions qiskit/compiler/transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from qiskit.circuit.quantumcircuit import QuantumCircuit
from qiskit.dagcircuit import DAGCircuit
from qiskit.providers.backend import Backend
from qiskit.providers.backend_compat import BackendV2Converter
from qiskit.pulse import Schedule
from qiskit.transpiler import Layout, CouplingMap, PropertySet
from qiskit.transpiler.basepasses import BasePass
Expand Down Expand Up @@ -95,21 +94,20 @@ def transpile( # pylint: disable=too-many-return-statements
(``basis_gates``, ``coupling_map``, ``instruction_durations``,
``dt`` or ``timing_constraints``). If a ``backend`` is provided together with any loose constraint
from the list above, the loose constraint will take priority over the corresponding backend
constraint. This behavior is independent of whether the ``backend`` instance is of type
:class:`.BackendV1` or :class:`.BackendV2`, as summarized in the table below. The first column
constraint. This behavior is summarized in the table below. The first column
in the table summarizes the potential user-provided constraints, and each cell shows whether
the priority is assigned to that specific constraint input or another input
(`target`/`backend(V1)`/`backend(V2)`).
============================ ========= ======================== =======================
User Provided target backend(V1) backend(V2)
============================ ========= ======================== =======================
**basis_gates** target basis_gates basis_gates
**coupling_map** target coupling_map coupling_map
**instruction_durations** target instruction_durations instruction_durations
**dt** target dt dt
**timing_constraints** target timing_constraints timing_constraints
============================ ========= ======================== =======================
(`target`/`backend(V2)`).
============================ ========= ========================
User Provided target backend(V2)
============================ ========= ========================
**basis_gates** target basis_gates
**coupling_map** target coupling_map
**instruction_durations** target instruction_durations
**dt** target dt
**timing_constraints** target timing_constraints
============================ ========= ========================
Args:
circuits: Circuit(s) to transpile
Expand Down Expand Up @@ -320,30 +318,6 @@ def callback_func(**kwargs):
config = user_config.get_config()
optimization_level = config.get("transpile_optimization_level", 2)

if backend is not None and getattr(backend, "version", 0) <= 1:
warnings.warn(
"The `transpile` function will stop supporting inputs of "
f"type `BackendV1` ( {backend} ) in the `backend` parameter in a future "
"release no earlier than 2.0. `BackendV1` is deprecated and implementations "
"should move to `BackendV2`.",
category=DeprecationWarning,
stacklevel=2,
)
with warnings.catch_warnings():
# This is a temporary conversion step to allow for a smoother transition
# to a fully target-based transpiler pipeline while maintaining the behavior
# of `transpile` with BackendV1 inputs.
# TODO BackendV1 is deprecated and this path can be
# removed once it gets removed:
# https://github.com/Qiskit/qiskit/pull/12850
warnings.filterwarnings(
"ignore",
category=DeprecationWarning,
message=r".+qiskit\.providers\.backend_compat\.BackendV2Converter.+",
module="qiskit",
)
backend = BackendV2Converter(backend)

if (
scheduling_method is not None
and backend is None
Expand Down
14 changes: 6 additions & 8 deletions qiskit/primitives/backend_estimator_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

from qiskit.circuit import ClassicalRegister, QuantumCircuit, QuantumRegister
from qiskit.exceptions import QiskitError
from qiskit.providers import BackendV1, BackendV2
from qiskit.providers import BackendV2
from qiskit.quantum_info import Pauli, PauliList
from qiskit.result import Counts, Result
from qiskit.transpiler import PassManager, PassManagerConfig
Expand All @@ -38,7 +38,7 @@

def _run_circuits(
circuits: QuantumCircuit | list[QuantumCircuit],
backend: BackendV1 | BackendV2,
backend: BackendV2,
clear_metadata: bool = True,
**run_options,
) -> tuple[list[Result], list[dict]]:
Expand All @@ -59,9 +59,7 @@ def _run_circuits(
metadata.append(circ.metadata)
if clear_metadata:
circ.metadata = {}
if isinstance(backend, BackendV1):
max_circuits = getattr(backend.configuration(), "max_experiments", None)
elif isinstance(backend, BackendV2):
if isinstance(backend, BackendV2):
max_circuits = backend.max_circuits
else:
raise RuntimeError("Backend version not supported")
Expand Down Expand Up @@ -174,7 +172,7 @@ class BackendEstimatorV2(BaseEstimatorV2):
The :class:`~.BackendEstimatorV2` class is a generic implementation of the
:class:`~.BaseEstimatorV2` interface that is used to wrap a :class:`~.BackendV2`
(or :class:`~.BackendV1`) object in the :class:`~.BaseEstimatorV2` API. It
object in the :class:`~.BaseEstimatorV2` API. It
facilitates using backends that do not provide a native
:class:`~.BaseEstimatorV2` implementation in places that work with
:class:`~.BaseEstimatorV2`. However,
Expand Down Expand Up @@ -225,7 +223,7 @@ class BackendEstimatorV2(BaseEstimatorV2):
def __init__(
self,
*,
backend: BackendV1 | BackendV2,
backend: BackendV2,
options: dict | None = None,
):
"""
Expand All @@ -251,7 +249,7 @@ def options(self) -> Options:
return self._options

@property
def backend(self) -> BackendV1 | BackendV2:
def backend(self) -> BackendV2:
"""Returns the backend which this sampler object based on."""
return self._backend

Expand Down
8 changes: 4 additions & 4 deletions qiskit/primitives/backend_sampler_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from qiskit.primitives.containers.bit_array import _min_num_bytes
from qiskit.primitives.containers.sampler_pub import SamplerPub
from qiskit.primitives.primitive_job import PrimitiveJob
from qiskit.providers.backend import BackendV1, BackendV2
from qiskit.providers.backend import BackendV2
from qiskit.result import Result


Expand Down Expand Up @@ -83,7 +83,7 @@ class BackendSamplerV2(BaseSamplerV2):
The :class:`~.BackendSamplerV2` class is a generic implementation of the
:class:`~.BaseSamplerV2` interface that is used to wrap a :class:`~.BackendV2`
(or :class:`~.BackendV1`) object in the class :class:`~.BaseSamplerV2` API. It
object in the class :class:`~.BaseSamplerV2` API. It
facilitates using backends that do not provide a native
:class:`~.BaseSamplerV2` implementation in places that work with
:class:`~.BaseSamplerV2`. However,
Expand Down Expand Up @@ -119,7 +119,7 @@ class BackendSamplerV2(BaseSamplerV2):
def __init__(
self,
*,
backend: BackendV1 | BackendV2,
backend: BackendV2,
options: dict | None = None,
):
"""
Expand All @@ -132,7 +132,7 @@ def __init__(
self._options = Options(**options) if options else Options()

@property
def backend(self) -> BackendV1 | BackendV2:
def backend(self) -> BackendV2:
"""Returns the backend which this sampler object based on."""
return self._backend

Expand Down
118 changes: 2 additions & 116 deletions qiskit/providers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
provider is anything that provides an external service to Qiskit. The typical
example of this is a Backend provider which provides
:class:`~qiskit.providers.Backend` objects which can be used for executing
:class:`~qiskit.circuit.QuantumCircuit` and/or :class:`~qiskit.pulse.Schedule`
:class:`~qiskit.circuit.QuantumCircuit`
objects. This module contains the abstract classes which are used to define the
interface between a provider and Qiskit.
Expand Down Expand Up @@ -82,11 +82,8 @@
:toctree: ../stubs/
Backend
BackendV1
BackendV2
QubitProperties
BackendV2Converter
convert_to_target
Options
-------
Expand Down Expand Up @@ -117,10 +114,8 @@
----------
.. autoexception:: QiskitBackendNotFoundError
.. autoexception:: BackendPropertyError
.. autoexception:: JobError
.. autoexception:: JobTimeoutError
.. autoexception:: BackendConfigurationError
Writing a New Backend
=====================
Expand Down Expand Up @@ -559,7 +554,7 @@ def _default_options(cls):
For some backends (mainly local simulators) the execution of circuits is a
synchronous operation and there is no need to return a handle to a running job
elsewhere. For sync jobs its expected that the
:obj:`~qiskit.providers.BackendV1.run` method on the backend will block until a
:obj:`~qiskit.providers.BackendV2.run` method on the backend will block until a
:class:`~qiskit.result.Result` object is generated and the sync job will return
with that inner :class:`~qiskit.result.Result` object.
Expand Down Expand Up @@ -603,7 +598,6 @@ def result(self, timeout=None, wait=5):
'backend_name': self._backend.configuration().backend_name,
'backend_version': self._backend.configuration().backend_version,
'job_id': self._job_id,
'qobj_id': ', '.join(x.name for x in self.circuits),
'success': True,
})
Expand Down Expand Up @@ -666,118 +660,12 @@ def status(self):
implementations. Also, the built-in implementations: :class:`~.Sampler`,
:class:`~.Estimator`, :class:`~.BackendSampler`, and :class:`~.BackendEstimator`
can serve as references/models on how to implement these as well.
Migrating from BackendV1 to BackendV2
=====================================
The :obj:`~BackendV2` class re-defined user access for most properties of a
backend to make them work with native Qiskit data structures and have flatter
access patterns. However this means when using a provider that upgrades
from :obj:`~BackendV1` to :obj:`~BackendV2` existing access patterns will need
to be adjusted. It is expected for existing providers to deprecate the old
access where possible to provide a graceful migration, but eventually users
will need to adjust code. The biggest change to adapt to in :obj:`~BackendV2` is
that most of the information accessible about a backend is contained in its
:class:`~qiskit.transpiler.Target` object and the backend's attributes often query
its :attr:`~qiskit.providers.BackendV2.target`
attribute to return information, however in many cases the attributes only provide
a subset of information the target can contain. For example, ``backend.coupling_map``
returns a :class:`~qiskit.transpiler.CouplingMap` constructed from the
:class:`~qiskit.transpiler.Target` accessible in the
:attr:`~qiskit.providers.BackendV2.target` attribute, however the target may contain
instructions that operate on more than two qubits (which can't be represented in a
:class:`~qiskit.transpiler.CouplingMap`) or has instructions that only operate on
a subset of qubits (or two qubit links for a two qubit instruction) which won't be
detailed in the full coupling map returned by
:attr:`~qiskit.providers.BackendV2.coupling_map`. So depending on your use case
it might be necessary to look deeper than just the equivalent access with
:obj:`~BackendV2`.
Below is a table of example access patterns in :obj:`~BackendV1` and the new form
with :obj:`~BackendV2`:
.. list-table:: Migrate from :obj:`~BackendV1` to :obj:`~BackendV2`
:header-rows: 1
* - :obj:`~BackendV1`
- :obj:`~BackendV2`
- Notes
* - ``backend.configuration().n_qubits``
- ``backend.num_qubits``
-
* - ``backend.configuration().coupling_map``
- ``backend.coupling_map``
- The return from :obj:`~BackendV2` is a :class:`~qiskit.transpiler.CouplingMap` object.
while in :obj:`~BackendV1` it is an edge list. Also this is just a view of
the information contained in ``backend.target`` which may only be a subset of the
information contained in :class:`~qiskit.transpiler.Target` object.
* - ``backend.configuration().backend_name``
- ``backend.name``
-
* - ``backend.configuration().backend_version``
- ``backend.backend_version``
- The :attr:`~qiskit.providers.BackendV2.version` attribute represents
the version of the abstract :class:`~qiskit.providers.Backend` interface
the object implements while :attr:`~qiskit.providers.BackendV2.backend_version`
is metadata about the version of the backend itself.
* - ``backend.configuration().basis_gates``
- ``backend.operation_names``
- The :obj:`~BackendV2` return is a list of operation names contained in the
``backend.target`` attribute. The :class:`~qiskit.transpiler.Target` may contain more
information that can be expressed by this list of names. For example, that some
operations only work on a subset of qubits or that some names implement the same gate
with different parameters.
* - ``backend.configuration().dt``
- ``backend.dt``
-
* - ``backend.configuration().dtm``
- ``backend.dtm``
-
* - ``backend.configuration().max_experiments``
- ``backend.max_circuits``
-
* - ``backend.configuration().online_date``
- ``backend.online_date``
-
* - ``InstructionDurations.from_backend(backend)``
- ``backend.instruction_durations``
-
* - ``backend.defaults().instruction_schedule_map``
- ``backend.instruction_schedule_map``
-
* - ``backend.properties().t1(0)``
- ``backend.qubit_properties(0).t1``
-
* - ``backend.properties().t2(0)``
- ``backend.qubit_properties(0).t2``
-
* - ``backend.properties().frequency(0)``
- ``backend.qubit_properties(0).frequency``
-
* - ``backend.properties().readout_error(0)``
- ``backend.target["measure"][(0,)].error``
- In :obj:`~BackendV2` the error rate for the :class:`~qiskit.circuit.library.Measure`
operation on a given qubit is used to model the readout error. However a
:obj:`~BackendV2` can implement multiple measurement types and list them
separately in a :class:`~qiskit.transpiler.Target`.
* - ``backend.properties().readout_length(0)``
- ``backend.target["measure"][(0,)].duration``
- In :obj:`~BackendV2` the duration for the :class:`~qiskit.circuit.library.Measure`
operation on a given qubit is used to model the readout length. However, a
:obj:`~BackendV2` can implement multiple measurement types and list them
separately in a :class:`~qiskit.transpiler.Target`.
There is also a :class:`~.BackendV2Converter` class available that enables you
to wrap a :class:`~.BackendV1` object with a :class:`~.BackendV2` interface.
"""

# Providers interface
from qiskit.providers.backend import Backend
from qiskit.providers.backend import BackendV1
from qiskit.providers.backend import BackendV2
from qiskit.providers.backend import QubitProperties
from qiskit.providers.backend_compat import BackendV2Converter
from qiskit.providers.backend_compat import convert_to_target
from qiskit.providers.options import Options
from qiskit.providers.job import Job
from qiskit.providers.job import JobV1
Expand All @@ -786,7 +674,5 @@ def status(self):
JobError,
JobTimeoutError,
QiskitBackendNotFoundError,
BackendPropertyError,
BackendConfigurationError,
)
from qiskit.providers.jobstatus import JobStatus
Loading

0 comments on commit 9c00a93

Please sign in to comment.