Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate provider-specific fake backends,FakeProvider class and related tools in 0.46 #11381

Merged
merged 10 commits into from
Jan 31, 2024
Merged
14 changes: 13 additions & 1 deletion qiskit/providers/fake_provider/fake_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class FakeBackendV2(BackendV2):

The class inherits :class:`~qiskit.providers.BackendV2` class. This version
differs from earlier :class:`~qiskit.providers.fake_provider.FakeBackend` (V1) class in a
few aspects. Firstly, configuration attribute no longer exsists. Instead,
few aspects. Firstly, configuration attribute no longer exists. Instead,
attributes exposing equivalent required immutable properties of the backend
device are added. For example ``fake_backend.configuration().n_qubits`` is
accessible from ``fake_backend.num_qubits`` now. Secondly, this version
Expand All @@ -73,6 +73,18 @@ class FakeBackendV2(BackendV2):

def __init__(self):
"""FakeBackendV2 initializer."""
# This is a deprecation warning for the subclasses.
# FakeBackendV2 is not deprecated.
warnings.warn(
message="Device-specific fake backends have been migrated to the "
"`qiskit_ibm_runtime` package. These classes are deprecated "
"as of qiskit 0.46.0 and will be removed in qiskit 1.0.0. "
"You should migrate your code to use "
"`from qiskit_ibm_runtime.fake_provider import FakeExample` "
"instead of `from qiskit.providers.fake_provider import FakeExample`.",
category=DeprecationWarning,
stacklevel=3,
)
self._conf_dict = self._get_conf_dict_from_json()
self._props_dict = None
self._defs_dict = None
Expand Down
22 changes: 22 additions & 0 deletions qiskit/providers/fake_provider/fake_backend_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,19 @@
from qiskit.providers.options import Options
from qiskit.transpiler import Target, InstructionProperties
from qiskit.providers.basic_provider.basic_simulator import BasicSimulator
from qiskit.utils.deprecation import deprecate_func


class FakeBackendV2(BackendV2):
"""A mock backend that doesn't implement run() to test compatibility with Terra internals."""

@deprecate_func(
additional_msg="Use the `qiskit.providers.basic_provider.GenericBackendV2` "
"class instead.",
since="0.46.0",
removal_timeline="Qiskit 1.0",
package_name="qiskit",
)
def __init__(self):
super().__init__(
None,
Expand Down Expand Up @@ -111,6 +119,13 @@ def qubit_properties(self, qubit):
class FakeBackend5QV2(BackendV2):
"""A mock backend that doesn't implement run() to test compatibility with Terra internals."""

@deprecate_func(
additional_msg="Use the `qiskit.providers.basic_provider.GenericBackendV2` "
"class instead.",
since="0.46.0",
removal_timeline="Qiskit 1.0",
package_name="qiskit",
)
def __init__(self, bidirectional=True):
super().__init__(
None,
Expand Down Expand Up @@ -183,6 +198,13 @@ def run(self, run_input, **options):
class FakeBackendSimple(BackendV2):
"""A fake simple backend that wraps BasicSimulator to implement run()."""

@deprecate_func(
additional_msg="Use the `qiskit.providers.basic_provider.GenericBackendV2` "
"class instead.",
since="0.46.0",
removal_timeline="Qiskit 1.0",
package_name="qiskit",
)
def __init__(self):
super().__init__(
None,
Expand Down
7 changes: 7 additions & 0 deletions qiskit/providers/fake_provider/fake_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,20 @@

from qiskit.providers import JobV1
from qiskit.providers.jobstatus import JobStatus
from qiskit.utils.deprecation import deprecate_func


class FakeJob(JobV1):
"""Fake simulator job"""

_executor = futures.ThreadPoolExecutor()

@deprecate_func(
additional_msg="Use the `qiskit.providers.JobV1` class instead.",
since="0.46.0",
removal_timeline="Qiskit 1.0",
package_name="qiskit",
)
def __init__(self, backend, job_id, fn):
super().__init__(backend, job_id)
self._backend = backend
Expand Down
8 changes: 8 additions & 0 deletions qiskit/providers/fake_provider/fake_mumbai_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,19 @@
from qiskit.providers.backend import BackendV2, QubitProperties
from qiskit.providers.options import Options
from qiskit.transpiler import Target, InstructionProperties
from qiskit.utils.deprecation import deprecate_func


class FakeMumbaiFractionalCX(BackendV2):
"""A fake mumbai backend."""

@deprecate_func(
additional_msg="Use the `qiskit.providers.basic_provider.GenericBackendV2` "
"class instead.",
since="0.46.0",
removal_timeline="Qiskit 1.0",
package_name="qiskit",
)
def __init__(self):
super().__init__(
name="FakeMumbaiFractionalCX",
Expand Down
28 changes: 27 additions & 1 deletion qiskit/providers/fake_provider/fake_provider.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2019.
# (C) Copyright IBM 2019, 2023.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
Expand All @@ -18,6 +18,7 @@

from qiskit.providers.provider import ProviderV1
from qiskit.providers.exceptions import QiskitBackendNotFoundError
from qiskit.utils.deprecation import deprecate_func

from .backends import *
from .fake_qasm_simulator import FakeQasmSimulator
Expand All @@ -28,6 +29,15 @@
class FakeProviderFactory:
"""Fake provider factory class."""

@deprecate_func(
additional_msg="This class has been migrated to the `qiskit_ibm_runtime` package. "
"You should migrate your code to "
"use `from qiskit_ibm_runtime.fake_provider import FakeProviderExample` "
"instead of `from qiskit.providers.fake_provider import FakeProviderExample`.",
since="0.46.0",
removal_timeline="Qiskit 1.0",
package_name="qiskit",
)
def __init__(self):
self.fake_provider = FakeProvider()

Expand Down Expand Up @@ -86,6 +96,14 @@ def get_backend(self, name=None, **kwargs):
def backends(self, name=None, **kwargs):
return self._backends

@deprecate_func(
additional_msg="This class has been migrated to the `qiskit_ibm_runtime` package. "
"You should migrate your code to "
"use `from qiskit_ibm_runtime.fake_provider import FakeProviderExample` "
"instead of `from qiskit.providers.fake_provider import FakeProviderExample`.",
since="0.46.0",
package_name="qiskit",
)
def __init__(self):
self._backends = [
FakeAlmadenV2(),
Expand Down Expand Up @@ -160,6 +178,14 @@ def get_backend(self, name=None, **kwargs):
def backends(self, name=None, **kwargs):
return self._backends

@deprecate_func(
additional_msg="This class has been migrated to the `qiskit_ibm_runtime` package. "
"You should migrate your code to "
"use `from qiskit_ibm_runtime.fake_provider import FakeProviderExample` "
"instead of `from qiskit.providers.fake_provider import FakeProviderExample`.",
since="0.46.0",
package_name="qiskit",
)
def __init__(self):
self._backends = [
FakeAlmaden(),
Expand Down
17 changes: 17 additions & 0 deletions qiskit/providers/fake_provider/fake_pulse_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
Fake backend abstract class for mock backends supporting OpenPulse.
"""

import warnings

from qiskit.exceptions import QiskitError
from qiskit.providers.models import PulseBackendConfiguration, PulseDefaults

Expand All @@ -26,6 +28,21 @@ class FakePulseBackend(FakeQasmBackend):

defs_filename = None

def __init__(self):
# This is a deprecation warning for the subclasses.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this class still used by anything in Qiskit? And, how about FakeBackendV1 which this ultimately uses as a base class? Can all of this be deprecated?

Copy link
Contributor

@kevinhartman kevinhartman Jan 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see, you're doing this in a separate PR it looks like 😄.

Or wait, are you? I'm a bit confused since I would think this file wouldn't have changes at all here since it's part of the V1 hierarchy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is confusing, but the V1 base classes (FakeBackendV1, FakePulseBackend, FakeQasmBackend) cannot be deprecated yet because they are used in the "generic" backend version too. The "fake backend alternatives" in #10952 are effectively snapshot-based fake backends with "more generic" names. This was agreed to be the best temporary alternative while BackendV1 is around, the plan is to eventually fully transition to BackendV2 but this will not happen for 1.0.

So now we have the challenge to deprecate ~45 subclasses without deprecating the base classes. This warning is only for the subclasses, and this is why I don't use the decorator here, so that the message doesn't say "FakeBackendV1 is deprecated" but "All fake backend instances based on real device snapshots...". And about the V1 hierarchy, I am taking advantage of the fact that these "V1 alternatives" to fake backends live on the main branch and the deprecations live on 0.46, so the warning would never appear on the non-deprecated alternatives.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah okay, thank you! I was missing that subtly 😄.

# FakePulseBackend is not deprecated.
warnings.warn(
message="Device-specific fake backends have been migrated to the "
"`qiskit_ibm_runtime` package. These classes are deprecated "
"as of qiskit 0.46.0 and will be removed in qiskit 1.0.0. "
"You should migrate your code to use "
"`from qiskit_ibm_runtime.fake_provider import FakeExample` "
"instead of `from qiskit.providers.fake_provider import FakeExample`.",
category=DeprecationWarning,
stacklevel=3,
)
super().__init__()

def defaults(self):
"""Returns a snapshot of device defaults"""
if not self._defaults:
Expand Down
15 changes: 14 additions & 1 deletion qiskit/providers/fake_provider/fake_qasm_backend.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2020.
# (C) Copyright IBM 2020, 2023.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
Expand All @@ -16,6 +16,7 @@

import json
import os
import warnings

from qiskit.exceptions import QiskitError
from qiskit.providers.models import BackendProperties, QasmBackendConfiguration
Expand All @@ -36,6 +37,18 @@ class FakeQasmBackend(FakeBackend):
backend_name = None

def __init__(self):
# This is a deprecation warning for the subclasses.
# FakeQasmBackend is not deprecated.
warnings.warn(
message="Device-specific fake backends have been migrated to the "
"`qiskit_ibm_runtime` package. These classes are deprecated "
"as of qiskit 0.46.0 and will be removed in qiskit 1.0.0. "
"You should migrate your code to use "
"`from qiskit_ibm_runtime.fake_provider import FakeExample` "
"instead of `from qiskit.providers.fake_provider import FakeExample`.",
category=DeprecationWarning,
stacklevel=3,
)
configuration = self._get_conf_from_json()
self._defaults = None
self._properties = None
Expand Down
7 changes: 7 additions & 0 deletions qiskit/providers/fake_provider/fake_qasm_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,20 @@
"""

from qiskit.providers.models import GateConfig, QasmBackendConfiguration
from qiskit.utils.deprecation import deprecate_func

from .fake_backend import FakeBackend


class FakeQasmSimulator(FakeBackend):
"""A fake simulator backend."""

@deprecate_func(
additional_msg="Use the `qiskit.providers.basic_provider.BasicSimulator` " "class instead.",
since="0.46.0",
removal_timeline="Qiskit 1.0",
package_name="qiskit",
)
def __init__(self):
configuration = QasmBackendConfiguration(
backend_name="fake_qasm_simulator",
Expand Down
7 changes: 7 additions & 0 deletions qiskit/providers/fake_provider/fake_qobj.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,20 @@
QasmQobjExperiment,
QasmQobjConfig,
)
from qiskit.utils.deprecation import deprecate_func

from .fake_qasm_simulator import FakeQasmSimulator


class FakeQobj(QasmQobj):
"""A fake `Qobj` instance."""

@deprecate_func(
additional_msg="Use the `qiskit.qobj.QasmQobj` class instead.",
since="0.46.0",
removal_timeline="Qiskit 1.0",
package_name="qiskit",
)
def __init__(self):
qobj_id = "test_id"
config = QasmQobjConfig(shots=1024, memory_slots=1)
Expand Down
10 changes: 8 additions & 2 deletions qiskit/test/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,6 @@ def setUpClass(cls):
]
for msg in allow_DeprecationWarning_message:
warnings.filterwarnings("default", category=DeprecationWarning, message=msg)

allow_aer_DeprecationWarning_message = [
# This warning should be fixed once Qiskit/qiskit-aer#1761 is in a release version of Aer.
"Setting metadata to None.*",
Expand All @@ -257,11 +256,18 @@ def setUpClass(cls):
"The qiskit.extensions module is deprecated since Qiskit 0.46.0. It will be removed "
"in the Qiskit 1.0 release.",
]

for msg in allow_aer_DeprecationWarning_message:
warnings.filterwarnings(
"default", category=DeprecationWarning, module="qiskit_aer.*", message=msg
)
# Ignore fake backend deprecation warnings to avoid over-crowding the test log
ignore_fake_backend_message = (
r"Device-specific fake backends have been migrated "
r"to the `qiskit_ibm_runtime` package.*"
)
warnings.filterwarnings(
"ignore", category=DeprecationWarning, message=ignore_fake_backend_message
)


class FullQiskitTestCase(QiskitTestCase):
Expand Down
50 changes: 50 additions & 0 deletions releasenotes/notes/deprecate-fake-backends-4dd275cf9a30d41f.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
deprecations:
- |
The core functionality of the :mod:`qiskit.providers.fake_provider` module has been migrated to
the new ``qiskit_ibm_runtime.fake_provider`` module. For this reason, the following elements in
the :mod:`qiskit.providers.fake_provider` have been deprecated as of Qiskit 0.46 and will be
removed in Qiskit 1.0:

* :class:`qiskit.providers.fake_provider.FakeProvider`
* :class:`qiskit.providers.fake_provider.FakeProviderForBackendV2`
* :class:`qiskit.providers.fake_provider.FakeProviderFactory`
* any fake backend contained in :class:`qiskit.providers.fake_provider.backends`
(accesible through the provider)
* :class:`qiskit.providers.fake_provider.FakeQasmSimulator`
* :class:`qiskit.providers.fake_provider.FakeJob`
* :class:`qiskit.providers.fake_provider.FakeQobj`

Migration example to the new fake provider::

# Legacy path
from qiskit.providers.fake_provider import FakeProvider, FakeSherbrooke
backend1 = FakeProvider().get_backend("fake_ourense")
backend2 = FakeSherbrooke()

# New path
# run "pip install qiskit-ibm-runtime"
from qiskit_ibm_runtime.fake_provider import FakeProvider, FakeSherbrooke
backend1 = FakeProvider().get_backend("fake_ourense")
backend2 = FakeSherbrooke()

Additionally, the following fake backends designed for special testing purposes have been superseded
by the new :class:`.GenericBackendV2` class, and are also deprecated as of Qiskit 0.46:

* :class:`qiskit.providers.fake_provider.fake_backend_v2.FakeBackendV2`
* :class:`qiskit.providers.fake_provider.fake_backend_v2.FakeBackendV2LegacyQubitProps`
* :class:`qiskit.providers.fake_provider.fake_backend_v2.FakeBackend5QV2`
* :class:`qiskit.providers.fake_provider.fake_backend_v2.FakeBackendSimple`

Migration example to the new :class:`.GenericBackendV2` class::

# 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 will generate 5q backend with generic
# properties that serves the same purpose as FakeBackend5QV2
# but will generate different results
4 changes: 3 additions & 1 deletion test/python/algorithms/test_backendv1.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ class TestBackendV1(QiskitAlgorithmsTestCase):

def setUp(self):
super().setUp()
self._provider = FakeProvider()
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=DeprecationWarning)
self._provider = FakeProvider()
self._qasm = self._provider.get_backend("fake_qasm_simulator")
self.seed = 50

Expand Down
7 changes: 5 additions & 2 deletions test/python/algorithms/test_backendv2.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"""Test Providers that support BackendV2 interface"""

import unittest
import warnings
from test.python.algorithms import QiskitAlgorithmsTestCase
from qiskit import QuantumCircuit
from qiskit.providers.fake_provider import FakeProvider
Expand All @@ -29,8 +30,10 @@ class TestBackendV2(QiskitAlgorithmsTestCase):

def setUp(self):
super().setUp()
self._provider = FakeProvider()
self._qasm = FakeBackendSimple()
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=DeprecationWarning)
self._provider = FakeProvider()
self._qasm = FakeBackendSimple()
self.seed = 50

def test_vqe_qasm(self):
Expand Down
Loading
Loading