From 76230d17e304eaec6a45f0cad99166cf5c225048 Mon Sep 17 00:00:00 2001 From: SamFerracin Date: Thu, 20 Jun 2024 14:34:40 -0400 Subject: [PATCH 01/10] basic functionality --- .../fake_provider/fake_backend.py | 4 + .../fake_provider/local_service.py | 92 ++++++++++++++++++- qiskit_ibm_runtime/qiskit_runtime_service.py | 4 +- 3 files changed, 95 insertions(+), 5 deletions(-) diff --git a/qiskit_ibm_runtime/fake_provider/fake_backend.py b/qiskit_ibm_runtime/fake_provider/fake_backend.py index a4d09ab42..cb65bca54 100644 --- a/qiskit_ibm_runtime/fake_provider/fake_backend.py +++ b/qiskit_ibm_runtime/fake_provider/fake_backend.py @@ -158,6 +158,10 @@ def _set_defs_dict_from_json(self) -> None: decode_pulse_defaults(defs_dict) self._defs_dict = defs_dict + def _supports_dynamic_circuits(self) -> bool: + supported_features = self._conf_dict.get("supported_features") or [] + return "qasm3" in supported_features + def _load_json(self, filename: str) -> dict: with open( # pylint: disable=unspecified-encoding os.path.join(self.dirname, filename) diff --git a/qiskit_ibm_runtime/fake_provider/local_service.py b/qiskit_ibm_runtime/fake_provider/local_service.py index 9b9717827..546df4c15 100644 --- a/qiskit_ibm_runtime/fake_provider/local_service.py +++ b/qiskit_ibm_runtime/fake_provider/local_service.py @@ -18,7 +18,8 @@ import logging import warnings from dataclasses import asdict -from typing import Dict, Literal, Union +from random import choice +from typing import Any, Callable, Dict, List, Literal, Optional, Union from qiskit.primitives import ( BackendEstimator, @@ -28,8 +29,12 @@ ) from qiskit.primitives.primitive_job import PrimitiveJob from qiskit.providers.backend import BackendV1, BackendV2 +from qiskit.providers.exceptions import QiskitBackendNotFoundError +from qiskit.providers.providerutils import filter_backends from qiskit.utils import optionals +from .fake_backend import FakeBackendV2 +from .fake_provider import FakeProviderForBackendV2 from ..ibm_backend import IBMBackend from ..runtime_options import RuntimeOptions @@ -39,9 +44,7 @@ class QiskitRuntimeLocalService: """Class for local testing mode.""" - def __init__( - self, - ) -> None: + def __init__(self) -> None: """QiskitRuntimeLocalService constructor. @@ -51,6 +54,87 @@ def __init__( """ self._channel_strategy = None + def backend(self, name: str = None) -> FakeBackendV2: + """Return a single fake backend matching the specified filters. + + Args: + name: The name of the backend. + + Returns: + Backend: A backend matching the filtering. + """ + return self.backends(name=name)[0] + + def backends( + self, + name: Optional[str] = None, + min_num_qubits: Optional[int] = None, + dynamic_circuits: Optional[bool] = None, + filters: Optional[Callable[[FakeBackendV2], bool]] = None, + ) -> List[FakeBackendV2]: + """Return all the available fake backends, subject to optional filtering. + + Args: + name: Backend name to filter by. + min_num_qubits: Minimum number of qubits the fake backend has to have. + dynamic_circuits: Filter by whether the fake backend supports dynamic circuits. + filters: More complex filters, such as lambda functions. + For example:: + + from qiskit_ibm_runtime.fake_provider.local_service import QiskitRuntimeLocalService + + QiskitRuntimeService.backends( + filters=lambda backend: (backend.online_date.year == 2021) + ) + QiskitRuntimeLocalService.backends( + filters=lambda backend: (backend.num_qubits > 30 and backend.num_qubits < 100) + ) + + Returns: + The list of available fake backends that match the filters. + + Raises: + QiskitBackendNotFoundError: If none of the available fake backends matches the given + filters. + """ + backends = FakeProviderForBackendV2().backends(name) + + if name: + for b in backends: + if b.name == name: + return [b] + + if min_num_qubits: + backends = [b for b in backends if b.num_qubits >= min_num_qubits] + + if dynamic_circuits: + backends = list(filter(lambda b: b._supports_dynamic_circuits() == dynamic_circuits, backends)) + + if not backends: + raise QiskitBackendNotFoundError("No backend matches the criteria.") + + return backends + + def least_busy( + self, + min_num_qubits: Optional[int] = None, + filters: Optional[Callable[[FakeBackendV2], bool]] = None, + ) -> FakeBackendV2: + """Mimics the :meth:`QiskitRuntimeService.least_busy` method by returning a randomly-chosen + fake backend. + + Args: + min_num_qubits: Minimum number of qubits the fake backend has to have. + instance: This is only supported for ``ibm_quantum`` runtime and is in the + hub/group/project format. + filters: More complex filters, such as lambda functions, that can be defined as for the + :meth:`backends` method. + + Returns: + A fake backend. + """ + return choice(self.backends(min_num_qubits=min_num_qubits, filters=filters)) + def run( self, program_id: Literal["sampler", "estimator"], diff --git a/qiskit_ibm_runtime/qiskit_runtime_service.py b/qiskit_ibm_runtime/qiskit_runtime_service.py index d3e483f74..abd6908a4 100644 --- a/qiskit_ibm_runtime/qiskit_runtime_service.py +++ b/qiskit_ibm_runtime/qiskit_runtime_service.py @@ -471,9 +471,11 @@ def backends( For example:: QiskitRuntimeService.backends( - filters=lambda b: b.max_shots > 50000) + filters=lambda b: b.max_shots > 50000 + ) QiskitRuntimeService.backends( filters=lambda x: ("rz" in x.basis_gates ) + ) use_fractional_gates: Set True to allow for the backends to include fractional gates in target. Currently this feature cannot be used simulataneously with the dynamic circuits, PEC, or PEA. From 195b6dc2507130532e743962b9cc3d676436ac37 Mon Sep 17 00:00:00 2001 From: SamFerracin Date: Thu, 20 Jun 2024 15:47:06 -0400 Subject: [PATCH 02/10] added tests --- .../fake_provider/local_service.py | 10 ++- test/unit/fake_provider/test_local_service.py | 78 +++++++++++++++++++ 2 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 test/unit/fake_provider/test_local_service.py diff --git a/qiskit_ibm_runtime/fake_provider/local_service.py b/qiskit_ibm_runtime/fake_provider/local_service.py index 546df4c15..4cf7f4ac8 100644 --- a/qiskit_ibm_runtime/fake_provider/local_service.py +++ b/qiskit_ibm_runtime/fake_provider/local_service.py @@ -98,20 +98,24 @@ def backends( filters. """ backends = FakeProviderForBackendV2().backends(name) + err = QiskitBackendNotFoundError("No backend matches the criteria.") if name: for b in backends: if b.name == name: return [b] + raise err if min_num_qubits: backends = [b for b in backends if b.num_qubits >= min_num_qubits] - if dynamic_circuits: - backends = list(filter(lambda b: b._supports_dynamic_circuits() == dynamic_circuits, backends)) + if dynamic_circuits is not None: + backends = [b for b in backends if b._supports_dynamic_circuits() == dynamic_circuits] + + backends = filter_backends(backends, filters=filters) if not backends: - raise QiskitBackendNotFoundError("No backend matches the criteria.") + raise err return backends diff --git a/test/unit/fake_provider/test_local_service.py b/test/unit/fake_provider/test_local_service.py new file mode 100644 index 000000000..454f85ae9 --- /dev/null +++ b/test/unit/fake_provider/test_local_service.py @@ -0,0 +1,78 @@ +# This code is part of Qiskit. +# +# (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 +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""Test of generated fake backends.""" +import unittest +from ddt import data, ddt + +from qiskit.providers.exceptions import QiskitBackendNotFoundError + +from qiskit_ibm_runtime.fake_provider.fake_backend import FakeBackendV2 +from qiskit_ibm_runtime.fake_provider import FakeAlgiers, FakeTorino, FakeProviderForBackendV2 +from qiskit_ibm_runtime.fake_provider.local_service import QiskitRuntimeLocalService +from ...ibm_test_case import IBMTestCase + + +@ddt +class QiskitRuntimeLocalServiceTest(IBMTestCase): + """Qiskit runtime local service test.""" + + service = QiskitRuntimeLocalService() + + def test_backend(self): + """Tests the ``backend`` method.""" + assert isinstance(self.service.backend(), FakeBackendV2) + assert isinstance(self.service.backend("fake_algiers"), FakeAlgiers) + assert isinstance(self.service.backend("fake_torino"), FakeTorino) + + def test_backends(self): + """Tests the ``backends`` method.""" + all_backends = self.service.backends() + expected = FakeProviderForBackendV2().backends() + assert len(all_backends) == len(expected) + + for b1, b2 in zip(all_backends, expected): + assert isinstance(b1, b2.__class__) + + def test_backends_name_filter(self): + """Tests the ``name`` filter of the ``backends`` method.""" + backends = self.service.backends("fake_torino") + assert len(backends) == 1 + assert isinstance(backends[0], FakeTorino) + + def test_backends_name_filter_error(self): + """Tests the error raised by an invalid name passed to the ``backends`` method.""" + with self.assertRaises(QiskitBackendNotFoundError): + self.service.backends("torino") + + def test_backends_min_num_qubits_filter(self): + """Tests the ``min_num_qubits`` filter of the ``backends`` method.""" + for b in self.service.backends(min_num_qubits=27): + assert b.num_qubits >= 27 + + @data(False, True) + def test_backends_dynamic_circuits_filter(self, supports): + """Tests the ``dynamic_circuits`` filter of the ``backends`` method.""" + for b in self.service.backends(dynamic_circuits=supports): + assert b._supports_dynamic_circuits() == supports + + def test_backends_filters(self): + """Tests the ``filters`` argument of the ``backends`` method.""" + for b in self.service.backends(filters=lambda b: (b.online_date.year == 2021)): + assert b.online_date.year == 2021 + + for b in self.service.backends(filters=lambda b: (b.num_qubits > 30 and b.num_qubits < 100)): + assert b.num_qubits > 30 and b.num_qubits < 100 + + def test_least_busy(self): + """Tests the ``least_busy`` method.""" + assert isinstance(self.service.least_busy(), FakeBackendV2) \ No newline at end of file From 67100cbbf1155bd91fc6c3093916be6943ef8f69 Mon Sep 17 00:00:00 2001 From: SamFerracin Date: Thu, 20 Jun 2024 16:03:09 -0400 Subject: [PATCH 03/10] for else --- .../fake_provider/local_service.py | 6 +++-- test/unit/fake_provider/test_local_service.py | 22 ++++++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/qiskit_ibm_runtime/fake_provider/local_service.py b/qiskit_ibm_runtime/fake_provider/local_service.py index 4cf7f4ac8..3bb2af97d 100644 --- a/qiskit_ibm_runtime/fake_provider/local_service.py +++ b/qiskit_ibm_runtime/fake_provider/local_service.py @@ -103,8 +103,10 @@ def backends( if name: for b in backends: if b.name == name: - return [b] - raise err + backends = [b] + break + else: + raise err if min_num_qubits: backends = [b for b in backends if b.num_qubits >= min_num_qubits] diff --git a/test/unit/fake_provider/test_local_service.py b/test/unit/fake_provider/test_local_service.py index 454f85ae9..3d8070b6b 100644 --- a/test/unit/fake_provider/test_local_service.py +++ b/test/unit/fake_provider/test_local_service.py @@ -49,11 +49,6 @@ def test_backends_name_filter(self): assert len(backends) == 1 assert isinstance(backends[0], FakeTorino) - def test_backends_name_filter_error(self): - """Tests the error raised by an invalid name passed to the ``backends`` method.""" - with self.assertRaises(QiskitBackendNotFoundError): - self.service.backends("torino") - def test_backends_min_num_qubits_filter(self): """Tests the ``min_num_qubits`` filter of the ``backends`` method.""" for b in self.service.backends(min_num_qubits=27): @@ -73,6 +68,23 @@ def test_backends_filters(self): for b in self.service.backends(filters=lambda b: (b.num_qubits > 30 and b.num_qubits < 100)): assert b.num_qubits > 30 and b.num_qubits < 100 + def test_backends_filters_combined(self): + """Tests the ``backends`` method with more than one filter.""" + backends1 = self.service.backends(name="fake_torino", min_num_qubits=27) + assert len(backends1) == 1 + assert isinstance(backends1[0], FakeTorino) + + backends2 = self.service.backends(min_num_qubits=27, filters=lambda b: (b.online_date.year == 2021)) + assert len(backends2) == 7 + + def test_backends_errors(self): + """Tests the errors raised by the ``backends`` method.""" + with self.assertRaises(QiskitBackendNotFoundError): + self.service.backends("torino") + + with self.assertRaises(QiskitBackendNotFoundError): + self.service.backends("fake_torino", filters=lambda b: (b.online_date.year == 1992)) + def test_least_busy(self): """Tests the ``least_busy`` method.""" assert isinstance(self.service.least_busy(), FakeBackendV2) \ No newline at end of file From 3ca833809858b916f857c3156a49afb1e12aa7af Mon Sep 17 00:00:00 2001 From: SamFerracin Date: Thu, 20 Jun 2024 16:04:33 -0400 Subject: [PATCH 04/10] instance --- qiskit_ibm_runtime/fake_provider/local_service.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/qiskit_ibm_runtime/fake_provider/local_service.py b/qiskit_ibm_runtime/fake_provider/local_service.py index 3bb2af97d..320a85448 100644 --- a/qiskit_ibm_runtime/fake_provider/local_service.py +++ b/qiskit_ibm_runtime/fake_provider/local_service.py @@ -131,8 +131,6 @@ def least_busy( Args: min_num_qubits: Minimum number of qubits the fake backend has to have. - instance: This is only supported for ``ibm_quantum`` runtime and is in the - hub/group/project format. filters: More complex filters, such as lambda functions, that can be defined as for the :meth:`backends` method. From 93681c50f30efe8ab4b5e92fc6dc266d725e2edb Mon Sep 17 00:00:00 2001 From: SamFerracin Date: Thu, 20 Jun 2024 16:11:58 -0400 Subject: [PATCH 05/10] style and mypy --- .../fake_provider/local_service.py | 8 ++-- test/unit/fake_provider/test_local_service.py | 46 +++++++++++-------- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/qiskit_ibm_runtime/fake_provider/local_service.py b/qiskit_ibm_runtime/fake_provider/local_service.py index 320a85448..9e4704692 100644 --- a/qiskit_ibm_runtime/fake_provider/local_service.py +++ b/qiskit_ibm_runtime/fake_provider/local_service.py @@ -107,20 +107,20 @@ def backends( break else: raise err - + if min_num_qubits: backends = [b for b in backends if b.num_qubits >= min_num_qubits] - if dynamic_circuits is not None: + if dynamic_circuits is not None: backends = [b for b in backends if b._supports_dynamic_circuits() == dynamic_circuits] backends = filter_backends(backends, filters=filters) if not backends: raise err - + return backends - + def least_busy( self, min_num_qubits: Optional[int] = None, diff --git a/test/unit/fake_provider/test_local_service.py b/test/unit/fake_provider/test_local_service.py index 3d8070b6b..18dab9fc7 100644 --- a/test/unit/fake_provider/test_local_service.py +++ b/test/unit/fake_provider/test_local_service.py @@ -26,65 +26,73 @@ class QiskitRuntimeLocalServiceTest(IBMTestCase): """Qiskit runtime local service test.""" - service = QiskitRuntimeLocalService() - def test_backend(self): """Tests the ``backend`` method.""" - assert isinstance(self.service.backend(), FakeBackendV2) - assert isinstance(self.service.backend("fake_algiers"), FakeAlgiers) - assert isinstance(self.service.backend("fake_torino"), FakeTorino) + service = QiskitRuntimeLocalService() + assert isinstance(service.backend(), FakeBackendV2) + assert isinstance(service.backend("fake_algiers"), FakeAlgiers) + assert isinstance(service.backend("fake_torino"), FakeTorino) def test_backends(self): """Tests the ``backends`` method.""" - all_backends = self.service.backends() + all_backends = QiskitRuntimeLocalService().backends() expected = FakeProviderForBackendV2().backends() assert len(all_backends) == len(expected) - + for b1, b2 in zip(all_backends, expected): assert isinstance(b1, b2.__class__) def test_backends_name_filter(self): """Tests the ``name`` filter of the ``backends`` method.""" - backends = self.service.backends("fake_torino") + backends = QiskitRuntimeLocalService().backends("fake_torino") assert len(backends) == 1 assert isinstance(backends[0], FakeTorino) def test_backends_min_num_qubits_filter(self): """Tests the ``min_num_qubits`` filter of the ``backends`` method.""" - for b in self.service.backends(min_num_qubits=27): + for b in QiskitRuntimeLocalService().backends(min_num_qubits=27): assert b.num_qubits >= 27 @data(False, True) def test_backends_dynamic_circuits_filter(self, supports): """Tests the ``dynamic_circuits`` filter of the ``backends`` method.""" - for b in self.service.backends(dynamic_circuits=supports): + for b in QiskitRuntimeLocalService().backends(dynamic_circuits=supports): assert b._supports_dynamic_circuits() == supports def test_backends_filters(self): """Tests the ``filters`` argument of the ``backends`` method.""" - for b in self.service.backends(filters=lambda b: (b.online_date.year == 2021)): + for b in QiskitRuntimeLocalService().backends( + filters=lambda b: (b.online_date.year == 2021) + ): assert b.online_date.year == 2021 - - for b in self.service.backends(filters=lambda b: (b.num_qubits > 30 and b.num_qubits < 100)): + + for b in QiskitRuntimeLocalService().backends( + filters=lambda b: (b.num_qubits > 30 and b.num_qubits < 100) + ): assert b.num_qubits > 30 and b.num_qubits < 100 def test_backends_filters_combined(self): """Tests the ``backends`` method with more than one filter.""" - backends1 = self.service.backends(name="fake_torino", min_num_qubits=27) + service = QiskitRuntimeLocalService() + + backends1 = service.backends(name="fake_torino", min_num_qubits=27) assert len(backends1) == 1 assert isinstance(backends1[0], FakeTorino) - backends2 = self.service.backends(min_num_qubits=27, filters=lambda b: (b.online_date.year == 2021)) + backends2 = service.backends( + min_num_qubits=27, filters=lambda b: (b.online_date.year == 2021) + ) assert len(backends2) == 7 def test_backends_errors(self): """Tests the errors raised by the ``backends`` method.""" - with self.assertRaises(QiskitBackendNotFoundError): - self.service.backends("torino") + service = QiskitRuntimeLocalService() with self.assertRaises(QiskitBackendNotFoundError): - self.service.backends("fake_torino", filters=lambda b: (b.online_date.year == 1992)) + service.backends("torino") + with self.assertRaises(QiskitBackendNotFoundError): + service.backends("fake_torino", filters=lambda b: (b.online_date.year == 1992)) def test_least_busy(self): """Tests the ``least_busy`` method.""" - assert isinstance(self.service.least_busy(), FakeBackendV2) \ No newline at end of file + assert isinstance(QiskitRuntimeLocalService().least_busy(), FakeBackendV2) From 149d51d706354e5a8c9f34bbffbe9c8557b7e1b3 Mon Sep 17 00:00:00 2001 From: SamFerracin Date: Thu, 20 Jun 2024 18:00:07 -0400 Subject: [PATCH 06/10] pylint --- qiskit_ibm_runtime/fake_provider/local_service.py | 4 ++-- test/unit/fake_provider/test_local_service.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/qiskit_ibm_runtime/fake_provider/local_service.py b/qiskit_ibm_runtime/fake_provider/local_service.py index 9e4704692..436714572 100644 --- a/qiskit_ibm_runtime/fake_provider/local_service.py +++ b/qiskit_ibm_runtime/fake_provider/local_service.py @@ -33,8 +33,8 @@ from qiskit.providers.providerutils import filter_backends from qiskit.utils import optionals -from .fake_backend import FakeBackendV2 -from .fake_provider import FakeProviderForBackendV2 +from .fake_backend import FakeBackendV2 # pylint: disable=cyclic-import +from .fake_provider import FakeProviderForBackendV2 # pylint: disable=unused-import, cyclic-import from ..ibm_backend import IBMBackend from ..runtime_options import RuntimeOptions diff --git a/test/unit/fake_provider/test_local_service.py b/test/unit/fake_provider/test_local_service.py index 18dab9fc7..73f68e3f9 100644 --- a/test/unit/fake_provider/test_local_service.py +++ b/test/unit/fake_provider/test_local_service.py @@ -11,7 +11,6 @@ # that they have been altered from the originals. """Test of generated fake backends.""" -import unittest from ddt import data, ddt from qiskit.providers.exceptions import QiskitBackendNotFoundError From 0ed6717707c74e829ba7f7100bf0ce7521020d23 Mon Sep 17 00:00:00 2001 From: SamFerracin Date: Thu, 20 Jun 2024 18:01:56 -0400 Subject: [PATCH 07/10] pylint --- qiskit_ibm_runtime/fake_provider/local_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit_ibm_runtime/fake_provider/local_service.py b/qiskit_ibm_runtime/fake_provider/local_service.py index 436714572..8450ea780 100644 --- a/qiskit_ibm_runtime/fake_provider/local_service.py +++ b/qiskit_ibm_runtime/fake_provider/local_service.py @@ -19,7 +19,7 @@ import warnings from dataclasses import asdict from random import choice -from typing import Any, Callable, Dict, List, Literal, Optional, Union +from typing import Callable, Dict, List, Literal, Optional, Union from qiskit.primitives import ( BackendEstimator, From d1e1511613f2db9014228673e05d68027efa212d Mon Sep 17 00:00:00 2001 From: SamFerracin Date: Fri, 21 Jun 2024 13:40:38 -0400 Subject: [PATCH 08/10] release note --- release-notes/0.24.1.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/release-notes/0.24.1.rst b/release-notes/0.24.1.rst index 44caab3e8..d9bd8035e 100644 --- a/release-notes/0.24.1.rst +++ b/release-notes/0.24.1.rst @@ -1,5 +1,9 @@ 0.24.1 (2024-06-18) =================== +New Features +------------ + +- Added ``backend``, ``backends``, and ``least_busy`` methods to ``QiskitRuntimeLocalService``. (`1764 `__) Bug Fixes --------- From 0ee6044a1e1046f2273df63b386e5b0ced46d89f Mon Sep 17 00:00:00 2001 From: SamFerracin Date: Tue, 25 Jun 2024 09:20:28 -0400 Subject: [PATCH 09/10] release notes --- release-notes/0.24.1.rst | 4 ---- release-notes/unreleased/1764.feat.rst | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) create mode 100644 release-notes/unreleased/1764.feat.rst diff --git a/release-notes/0.24.1.rst b/release-notes/0.24.1.rst index d9bd8035e..44caab3e8 100644 --- a/release-notes/0.24.1.rst +++ b/release-notes/0.24.1.rst @@ -1,9 +1,5 @@ 0.24.1 (2024-06-18) =================== -New Features ------------- - -- Added ``backend``, ``backends``, and ``least_busy`` methods to ``QiskitRuntimeLocalService``. (`1764 `__) Bug Fixes --------- diff --git a/release-notes/unreleased/1764.feat.rst b/release-notes/unreleased/1764.feat.rst new file mode 100644 index 000000000..71acba2a4 --- /dev/null +++ b/release-notes/unreleased/1764.feat.rst @@ -0,0 +1 @@ +Added ``backend``, ``backends``, and ``least_busy`` methods to ``QiskitRuntimeLocalService``. From 3663257cffaa56fbf5d7a30fa7b3b65fb10de454 Mon Sep 17 00:00:00 2001 From: SamFerracin Date: Wed, 26 Jun 2024 15:02:33 -0400 Subject: [PATCH 10/10] remove random choice --- qiskit_ibm_runtime/fake_provider/local_service.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qiskit_ibm_runtime/fake_provider/local_service.py b/qiskit_ibm_runtime/fake_provider/local_service.py index 8450ea780..d8ba49724 100644 --- a/qiskit_ibm_runtime/fake_provider/local_service.py +++ b/qiskit_ibm_runtime/fake_provider/local_service.py @@ -18,7 +18,6 @@ import logging import warnings from dataclasses import asdict -from random import choice from typing import Callable, Dict, List, Literal, Optional, Union from qiskit.primitives import ( @@ -137,7 +136,7 @@ def least_busy( Returns: A fake backend. """ - return choice(self.backends(min_num_qubits=min_num_qubits, filters=filters)) + return self.backends(min_num_qubits=min_num_qubits, filters=filters)[0] def run( self,