From d8cd3f1f7843ab416aacc780e8c2f3cb47f36da7 Mon Sep 17 00:00:00 2001 From: Melf Date: Fri, 3 Nov 2023 17:34:47 +0000 Subject: [PATCH 1/4] add seed list feature --- docs/changelog.rst | 1 + pytket/extensions/qiskit/backends/aer.py | 9 +-- pytket/extensions/qiskit/backends/ibm.py | 8 ++- .../extensions/qiskit/backends/ibm_utils.py | 62 ++++++++++++++----- .../qiskit/backends/ibmq_emulator.py | 10 +-- tests/backend_test.py | 58 +++++++++++++++++ 6 files changed, 122 insertions(+), 26 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index a35e309e..f23de430 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,6 +9,7 @@ unreleased * Update qiskit-ibm-runtime version to 0.13.0. * Update qiskit-aer version to 0.13.0. * Introduce dependency on qiskit-algorithms. +* Add possibility to submit list of seeds to backend in batch submission 0.45.0 (October 2023) --------------------- diff --git a/pytket/extensions/qiskit/backends/aer.py b/pytket/extensions/qiskit/backends/aer.py index 1ebe688c..1f5f579e 100644 --- a/pytket/extensions/qiskit/backends/aer.py +++ b/pytket/extensions/qiskit/backends/aer.py @@ -237,7 +237,7 @@ def process_circuits( circuits: Sequence[Circuit], n_shots: Union[None, int, Sequence[Optional[int]]] = None, valid_check: bool = True, - **kwargs: KwargTypes, + **kwargs: Union[int, float, str, None, Sequence[Optional[int]]], ) -> List[ResultHandle]: circuits = list(circuits) n_shots_list = Backend._get_n_shots_as_list( @@ -258,11 +258,13 @@ def process_circuits( circuits = noisy_circuits handle_list: List[Optional[ResultHandle]] = [None] * len(circuits) - circuit_batches, batch_order = _batch_circuits(circuits, n_shots_list) + circuit_batches, batch_order = _batch_circuits( + circuits, n_shots_list, kwargs.get("seed") + ) replace_implicit_swaps = self.supports_state or self.supports_unitary - for (n_shots, batch), indices in zip(circuit_batches, batch_order): + for (n_shots, seed, batch), indices in zip(circuit_batches, batch_order): qcs = [] for tkc in batch: qc = tk_to_qiskit(tkc, replace_implicit_swaps) @@ -275,7 +277,6 @@ def process_circuits( if self._needs_transpile: qcs = transpile(qcs, self._qiskit_backend) - seed = cast(Optional[int], kwargs.get("seed")) job = self._qiskit_backend.run( qcs, shots=n_shots, diff --git a/pytket/extensions/qiskit/backends/ibm.py b/pytket/extensions/qiskit/backends/ibm.py index 4d68e90e..0a405ecc 100644 --- a/pytket/extensions/qiskit/backends/ibm.py +++ b/pytket/extensions/qiskit/backends/ibm.py @@ -443,7 +443,7 @@ def process_circuits( circuits: Sequence[Circuit], n_shots: Union[None, int, Sequence[Optional[int]]] = None, valid_check: bool = True, - **kwargs: KwargTypes, + **kwargs: Union[int, float, str, None, Sequence[Optional[int]]], ) -> List[ResultHandle]: """ See :py:meth:`pytket.backends.Backend.process_circuits`. @@ -464,13 +464,15 @@ def process_circuits( ) handle_list: List[Optional[ResultHandle]] = [None] * len(circuits) - circuit_batches, batch_order = _batch_circuits(circuits, n_shots_list) + circuit_batches, batch_order = _batch_circuits( + circuits, n_shots_list, kwargs.get("seed") + ) postprocess = kwargs.get("postprocess", False) simplify_initial = kwargs.get("simplify_initial", False) batch_id = 0 # identify batches for debug purposes only - for (n_shots, batch), indices in zip(circuit_batches, batch_order): + for (n_shots, _, batch), indices in zip(circuit_batches, batch_order): for chunk in itertools.zip_longest( *([iter(zip(batch, indices))] * self._max_per_job) ): diff --git a/pytket/extensions/qiskit/backends/ibm_utils.py b/pytket/extensions/qiskit/backends/ibm_utils.py index 876274fe..8d7a69e9 100644 --- a/pytket/extensions/qiskit/backends/ibm_utils.py +++ b/pytket/extensions/qiskit/backends/ibm_utils.py @@ -16,7 +16,7 @@ """ import itertools -from typing import Collection, Optional, Sequence, Tuple, List, TYPE_CHECKING +from typing import Collection, Optional, Sequence, Tuple, List, TYPE_CHECKING, Union import numpy as np @@ -39,8 +39,10 @@ def _batch_circuits( - circuits: Sequence["Circuit"], n_shots: Sequence[Optional[int]] -) -> Tuple[List[Tuple[Optional[int], List["Circuit"]]], List[List[int]]]: + circuits: Sequence["Circuit"], + n_shots: Sequence[Optional[int]], + seed: Union[int, float, str, None, Sequence[Optional[int]]], +) -> Tuple[List[Tuple[Optional[int], Optional[int], List["Circuit"]]], List[List[int]]]: """ Groups circuits into sets of circuits with the same number of shots. @@ -50,17 +52,47 @@ def _batch_circuits( :type circuits: Sequence[Circuit] :param n_shots: Number of shots for each circuit. :type n_shots: Sequence[int] + :param seed: RNG Seed for each circuit. + :type seed: Union[int, None, Sequence[Optional[int]]] """ - # take care of None entries - n_shots_int = list(map(lambda x: x if x is not None else -1, n_shots)) - - order: Collection[int] = np.argsort(n_shots_int) - batches: List[Tuple[Optional[int], List["Circuit"]]] = [ - (n, [circuits[i] for i in indices]) - for n, indices in itertools.groupby(order, key=lambda i: n_shots[i]) - ] - batch_order: List[List[int]] = [ - list(indices) - for n, indices in itertools.groupby(order, key=lambda i: n_shots[i]) - ] + + n_seeds: list[Optional[int]] = [] + if type(seed) == list: + n_seeds = seed + elif type(seed) == int: + n_seeds = [seed for _ in range(len(circuits))] + elif seed == None: + n_seeds = [None for _ in range(len(circuits))] + else: + raise ValueError( + f"""unknown seed type, type should be None, +int, or list[int], type found {type(seed)}""" + ) + + assert len(n_seeds) == len(n_shots) + assert len(n_seeds) == len(circuits) + + batches: List[Tuple[Optional[int], Optional[int], List["Circuit"]]] = [] + batch_order: List[List[int]] = [] + + if all(seed == n_seeds[0] for seed in n_seeds): + # take care of None entries + n_shots_int = list(map(lambda x: x if x is not None else -1, n_shots)) + + order: Collection[int] = np.argsort(n_shots_int) + + batches = [ + (n, n_seeds[0], [circuits[i] for i in indices]) + for n, indices in itertools.groupby(order, key=lambda i: n_shots[i]) + ] + batch_order = [ + list(indices) + for n, indices in itertools.groupby(order, key=lambda i: n_shots[i]) + ] + else: + + for i in range(len(circuits)): + batches.append((n_shots[i], n_seeds[i], [circuits[i]])) + batch_order.append([i]) + return batches, batch_order diff --git a/pytket/extensions/qiskit/backends/ibmq_emulator.py b/pytket/extensions/qiskit/backends/ibmq_emulator.py index 490e92f0..7abecb58 100644 --- a/pytket/extensions/qiskit/backends/ibmq_emulator.py +++ b/pytket/extensions/qiskit/backends/ibmq_emulator.py @@ -125,7 +125,7 @@ def process_circuits( circuits: Sequence[Circuit], n_shots: Union[None, int, Sequence[Optional[int]]] = None, valid_check: bool = True, - **kwargs: KwargTypes, + **kwargs: Union[int, float, str, None, Sequence[Optional[int]]], ) -> List[ResultHandle]: """ See :py:meth:`pytket.backends.Backend.process_circuits`. @@ -139,10 +139,12 @@ def process_circuits( ) handle_list: List[Optional[ResultHandle]] = [None] * len(circuits) - circuit_batches, batch_order = _batch_circuits(circuits, n_shots_list) + circuit_batches, batch_order = _batch_circuits( + circuits, n_shots_list, kwargs.get("seed") + ) batch_id = 0 # identify batches for debug purposes only - for (n_shots, batch), indices in zip(circuit_batches, batch_order): + for (n_shots, seed, batch), indices in zip(circuit_batches, batch_order): for chunk in itertools.zip_longest( *([iter(zip(batch, indices))] * self._ibmq._max_per_job) ): @@ -173,7 +175,7 @@ def process_circuits( options.resilience_level = 0 options.execution.shots = n_shots options.simulator.noise_model = self._noise_model - options.seed_simulator = kwargs.get("seed") + options.seed_simulator = seed sampler = Sampler(session=self._session, options=options) job = sampler.run(circuits=qcs) job_id = job.job_id() diff --git a/tests/backend_test.py b/tests/backend_test.py index e4bd91be..f49b6d48 100644 --- a/tests/backend_test.py +++ b/tests/backend_test.py @@ -462,6 +462,64 @@ def test_nshots_batching(perth_backend: IBMQBackend) -> None: backend._MACHINE_DEBUG = False +@pytest.mark.skipif(skip_remote_tests, reason=REASON) +def test_nshots_nseeds_batching(perth_backend: IBMQBackend) -> None: + backend = perth_backend + backend._MACHINE_DEBUG = True + try: + c1 = Circuit(2, 2).H(0).CX(0, 1).measure_all() + c2 = Circuit(2, 2).Rx(0.5, 0).CX(0, 1).measure_all() + c3 = Circuit(2, 2).H(1).CX(0, 1).measure_all() + c4 = Circuit(2, 2).Rx(0.5, 0).CX(0, 1).CX(1, 0).measure_all() + cs = [c1, c2, c3, c4] + n_shots = [10, 12, 10, 13] + n_seeds = [10, 10, 10, 10] + cs = backend.get_compiled_circuits(cs) + handles = backend.process_circuits(cs, n_shots=n_shots, seed=n_seeds) + + from pytket.extensions.qiskit.backends.ibm import _DEBUG_HANDLE_PREFIX + + assert all( + cast(str, hand[0]) == _DEBUG_HANDLE_PREFIX + suffix + for hand, suffix in zip( + handles, + [f"{(10, 0)}", f"{(12, 1)}", f"{(10, 0)}", f"{(13, 2)}"], + ) + ) + finally: + # ensure shared backend is reset for other tests + backend._MACHINE_DEBUG = False + + +@pytest.mark.skipif(skip_remote_tests, reason=REASON) +def test_nshots_nseeds_batching_ii(perth_backend: IBMQBackend) -> None: + backend = perth_backend + backend._MACHINE_DEBUG = True + try: + c1 = Circuit(2, 2).H(0).CX(0, 1).measure_all() + c2 = Circuit(2, 2).Rx(0.5, 0).CX(0, 1).measure_all() + c3 = Circuit(2, 2).H(1).CX(0, 1).measure_all() + c4 = Circuit(2, 2).Rx(0.5, 0).CX(0, 1).CX(1, 0).measure_all() + cs = [c1, c2, c3, c4] + n_shots = [10, 12, 10, 13] + n_seeds = [10, 11, 12, 13] + cs = backend.get_compiled_circuits(cs) + handles = backend.process_circuits(cs, n_shots=n_shots, seed=n_seeds) + + from pytket.extensions.qiskit.backends.ibm import _DEBUG_HANDLE_PREFIX + + assert all( + cast(str, hand[0]) == _DEBUG_HANDLE_PREFIX + suffix + for hand, suffix in zip( + handles, + [f"{(10, 0)}", f"{(12, 1)}", f"{(10, 2)}", f"{(13, 3)}"], + ) + ) + finally: + # ensure shared backend is reset for other tests + backend._MACHINE_DEBUG = False + + @pytest.mark.flaky(reruns=3, reruns_delay=10) @pytest.mark.skipif(skip_remote_tests, reason=REASON) def test_nshots(perth_emulator_backend: IBMQEmulatorBackend) -> None: From 080f4535a763e62863531ab288b6cf29ab3a2ae3 Mon Sep 17 00:00:00 2001 From: Melf Date: Tue, 7 Nov 2023 18:25:22 +0000 Subject: [PATCH 2/4] remove list, add auto inc --- docs/changelog.rst | 2 +- pytket/extensions/qiskit/backends/aer.py | 17 ++++-- pytket/extensions/qiskit/backends/ibm.py | 8 +-- .../extensions/qiskit/backends/ibm_utils.py | 58 +++++-------------- .../qiskit/backends/ibmq_emulator.py | 15 +++-- tests/backend_test.py | 12 ++-- 6 files changed, 48 insertions(+), 64 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index f23de430..e3698772 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,7 +9,7 @@ unreleased * Update qiskit-ibm-runtime version to 0.13.0. * Update qiskit-aer version to 0.13.0. * Introduce dependency on qiskit-algorithms. -* Add possibility to submit list of seeds to backend in batch submission +* Add option for automatic incrementing seed on ``process_circuits()``. 0.45.0 (October 2023) --------------------- diff --git a/pytket/extensions/qiskit/backends/aer.py b/pytket/extensions/qiskit/backends/aer.py index 1f5f579e..e442edba 100644 --- a/pytket/extensions/qiskit/backends/aer.py +++ b/pytket/extensions/qiskit/backends/aer.py @@ -237,8 +237,14 @@ def process_circuits( circuits: Sequence[Circuit], n_shots: Union[None, int, Sequence[Optional[int]]] = None, valid_check: bool = True, - **kwargs: Union[int, float, str, None, Sequence[Optional[int]]], + **kwargs: Union[bool, int, float, str, None], ) -> List[ResultHandle]: + """ + See :py:meth:`pytket.backends.Backend.process_circuits`. + Supported kwargs: `seed`, `postprocess`, `seed_auto_increase`. + seed_auto_increase=True will automatically increase the seed by one for the + different batches when more than one circuit is submitted + """ circuits = list(circuits) n_shots_list = Backend._get_n_shots_as_list( n_shots, @@ -258,13 +264,12 @@ def process_circuits( circuits = noisy_circuits handle_list: List[Optional[ResultHandle]] = [None] * len(circuits) - circuit_batches, batch_order = _batch_circuits( - circuits, n_shots_list, kwargs.get("seed") - ) + seed = kwargs.get("seed") + circuit_batches, batch_order = _batch_circuits(circuits, n_shots_list) replace_implicit_swaps = self.supports_state or self.supports_unitary - for (n_shots, seed, batch), indices in zip(circuit_batches, batch_order): + for (n_shots, batch), indices in zip(circuit_batches, batch_order): qcs = [] for tkc in batch: qc = tk_to_qiskit(tkc, replace_implicit_swaps) @@ -284,6 +289,8 @@ def process_circuits( seed_simulator=seed, noise_model=self._noise_model, ) + if kwargs.get("seed_auto_increase") and type(seed) is int: + seed += 1 jobid = job.job_id() for i, ind in enumerate(indices): handle = ResultHandle(jobid, i) diff --git a/pytket/extensions/qiskit/backends/ibm.py b/pytket/extensions/qiskit/backends/ibm.py index 0a405ecc..b687bd1c 100644 --- a/pytket/extensions/qiskit/backends/ibm.py +++ b/pytket/extensions/qiskit/backends/ibm.py @@ -443,7 +443,7 @@ def process_circuits( circuits: Sequence[Circuit], n_shots: Union[None, int, Sequence[Optional[int]]] = None, valid_check: bool = True, - **kwargs: Union[int, float, str, None, Sequence[Optional[int]]], + **kwargs: Union[bool, int, float, str, None], ) -> List[ResultHandle]: """ See :py:meth:`pytket.backends.Backend.process_circuits`. @@ -464,15 +464,13 @@ def process_circuits( ) handle_list: List[Optional[ResultHandle]] = [None] * len(circuits) - circuit_batches, batch_order = _batch_circuits( - circuits, n_shots_list, kwargs.get("seed") - ) + circuit_batches, batch_order = _batch_circuits(circuits, n_shots_list) postprocess = kwargs.get("postprocess", False) simplify_initial = kwargs.get("simplify_initial", False) batch_id = 0 # identify batches for debug purposes only - for (n_shots, _, batch), indices in zip(circuit_batches, batch_order): + for (n_shots, batch), indices in zip(circuit_batches, batch_order): for chunk in itertools.zip_longest( *([iter(zip(batch, indices))] * self._max_per_job) ): diff --git a/pytket/extensions/qiskit/backends/ibm_utils.py b/pytket/extensions/qiskit/backends/ibm_utils.py index 8d7a69e9..6ade4566 100644 --- a/pytket/extensions/qiskit/backends/ibm_utils.py +++ b/pytket/extensions/qiskit/backends/ibm_utils.py @@ -41,8 +41,7 @@ def _batch_circuits( circuits: Sequence["Circuit"], n_shots: Sequence[Optional[int]], - seed: Union[int, float, str, None, Sequence[Optional[int]]], -) -> Tuple[List[Tuple[Optional[int], Optional[int], List["Circuit"]]], List[List[int]]]: +) -> Tuple[List[Tuple[Optional[int], List["Circuit"]]], List[List[int]]]: """ Groups circuits into sets of circuits with the same number of shots. @@ -52,47 +51,22 @@ def _batch_circuits( :type circuits: Sequence[Circuit] :param n_shots: Number of shots for each circuit. :type n_shots: Sequence[int] - :param seed: RNG Seed for each circuit. - :type seed: Union[int, None, Sequence[Optional[int]]] """ - n_seeds: list[Optional[int]] = [] - if type(seed) == list: - n_seeds = seed - elif type(seed) == int: - n_seeds = [seed for _ in range(len(circuits))] - elif seed == None: - n_seeds = [None for _ in range(len(circuits))] - else: - raise ValueError( - f"""unknown seed type, type should be None, -int, or list[int], type found {type(seed)}""" - ) - - assert len(n_seeds) == len(n_shots) - assert len(n_seeds) == len(circuits) - - batches: List[Tuple[Optional[int], Optional[int], List["Circuit"]]] = [] - batch_order: List[List[int]] = [] - - if all(seed == n_seeds[0] for seed in n_seeds): - # take care of None entries - n_shots_int = list(map(lambda x: x if x is not None else -1, n_shots)) - - order: Collection[int] = np.argsort(n_shots_int) - - batches = [ - (n, n_seeds[0], [circuits[i] for i in indices]) - for n, indices in itertools.groupby(order, key=lambda i: n_shots[i]) - ] - batch_order = [ - list(indices) - for n, indices in itertools.groupby(order, key=lambda i: n_shots[i]) - ] - else: - - for i in range(len(circuits)): - batches.append((n_shots[i], n_seeds[i], [circuits[i]])) - batch_order.append([i]) + assert len(n_shots) == len(circuits) + + # take care of None entries + n_shots_int = list(map(lambda x: x if x is not None else -1, n_shots)) + + order: Collection[int] = np.argsort(n_shots_int) + + batches: List[Tuple[Optional[int], List["Circuit"]]] = [ + (n, [circuits[i] for i in indices]) + for n, indices in itertools.groupby(order, key=lambda i: n_shots[i]) + ] + batch_order: List[List[int]] = [ + list(indices) + for n, indices in itertools.groupby(order, key=lambda i: n_shots[i]) + ] return batches, batch_order diff --git a/pytket/extensions/qiskit/backends/ibmq_emulator.py b/pytket/extensions/qiskit/backends/ibmq_emulator.py index 7abecb58..f74709fa 100644 --- a/pytket/extensions/qiskit/backends/ibmq_emulator.py +++ b/pytket/extensions/qiskit/backends/ibmq_emulator.py @@ -125,11 +125,13 @@ def process_circuits( circuits: Sequence[Circuit], n_shots: Union[None, int, Sequence[Optional[int]]] = None, valid_check: bool = True, - **kwargs: Union[int, float, str, None, Sequence[Optional[int]]], + **kwargs: Union[bool, int, float, str, None], ) -> List[ResultHandle]: """ See :py:meth:`pytket.backends.Backend.process_circuits`. - Supported kwargs: `seed`, `postprocess`. + Supported kwargs: `seed`, `postprocess`, `seed_auto_increase`. + seed_auto_increase=True will automatically increase the seed by one for the + different batches when more than one circuit is submitted """ circuits = list(circuits) n_shots_list = Backend._get_n_shots_as_list( @@ -139,12 +141,11 @@ def process_circuits( ) handle_list: List[Optional[ResultHandle]] = [None] * len(circuits) - circuit_batches, batch_order = _batch_circuits( - circuits, n_shots_list, kwargs.get("seed") - ) + seed = kwargs.get("seed") + circuit_batches, batch_order = _batch_circuits(circuits, n_shots_list) batch_id = 0 # identify batches for debug purposes only - for (n_shots, seed, batch), indices in zip(circuit_batches, batch_order): + for (n_shots, batch), indices in zip(circuit_batches, batch_order): for chunk in itertools.zip_longest( *([iter(zip(batch, indices))] * self._ibmq._max_per_job) ): @@ -176,6 +177,8 @@ def process_circuits( options.execution.shots = n_shots options.simulator.noise_model = self._noise_model options.seed_simulator = seed + if kwargs.get("seed_auto_increase") and type(seed) is int: + seed += 1 sampler = Sampler(session=self._session, options=options) job = sampler.run(circuits=qcs) job_id = job.job_id() diff --git a/tests/backend_test.py b/tests/backend_test.py index f49b6d48..041ca660 100644 --- a/tests/backend_test.py +++ b/tests/backend_test.py @@ -473,9 +473,10 @@ def test_nshots_nseeds_batching(perth_backend: IBMQBackend) -> None: c4 = Circuit(2, 2).Rx(0.5, 0).CX(0, 1).CX(1, 0).measure_all() cs = [c1, c2, c3, c4] n_shots = [10, 12, 10, 13] - n_seeds = [10, 10, 10, 10] cs = backend.get_compiled_circuits(cs) - handles = backend.process_circuits(cs, n_shots=n_shots, seed=n_seeds) + handles = backend.process_circuits( + cs, n_shots=n_shots, seed=10, seed_auto_increase=False + ) from pytket.extensions.qiskit.backends.ibm import _DEBUG_HANDLE_PREFIX @@ -502,9 +503,10 @@ def test_nshots_nseeds_batching_ii(perth_backend: IBMQBackend) -> None: c4 = Circuit(2, 2).Rx(0.5, 0).CX(0, 1).CX(1, 0).measure_all() cs = [c1, c2, c3, c4] n_shots = [10, 12, 10, 13] - n_seeds = [10, 11, 12, 13] cs = backend.get_compiled_circuits(cs) - handles = backend.process_circuits(cs, n_shots=n_shots, seed=n_seeds) + handles = backend.process_circuits( + cs, n_shots=n_shots, seed=10, seed_auto_increase=True + ) from pytket.extensions.qiskit.backends.ibm import _DEBUG_HANDLE_PREFIX @@ -512,7 +514,7 @@ def test_nshots_nseeds_batching_ii(perth_backend: IBMQBackend) -> None: cast(str, hand[0]) == _DEBUG_HANDLE_PREFIX + suffix for hand, suffix in zip( handles, - [f"{(10, 0)}", f"{(12, 1)}", f"{(10, 2)}", f"{(13, 3)}"], + [f"{(10, 0)}", f"{(12, 1)}", f"{(10, 0)}", f"{(13, 2)}"], ) ) finally: From 85489ef983300e4739976ba68048e55e5ceb932a Mon Sep 17 00:00:00 2001 From: Melf Date: Wed, 8 Nov 2023 14:05:59 +0000 Subject: [PATCH 3/4] requsted changes ii, make auto inc default, remove parameter --- docs/changelog.rst | 3 ++- pytket/extensions/qiskit/backends/aer.py | 6 ++---- pytket/extensions/qiskit/backends/ibmq_emulator.py | 6 ++---- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index e3698772..7248d698 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,7 +9,8 @@ unreleased * Update qiskit-ibm-runtime version to 0.13.0. * Update qiskit-aer version to 0.13.0. * Introduce dependency on qiskit-algorithms. -* Add option for automatic incrementing seed on ``process_circuits()``. +* Seed given to ``process_circuits()`` will be automaticly incremented + for the different circuit batches submitted. 0.45.0 (October 2023) --------------------- diff --git a/pytket/extensions/qiskit/backends/aer.py b/pytket/extensions/qiskit/backends/aer.py index e442edba..f196ad22 100644 --- a/pytket/extensions/qiskit/backends/aer.py +++ b/pytket/extensions/qiskit/backends/aer.py @@ -241,9 +241,7 @@ def process_circuits( ) -> List[ResultHandle]: """ See :py:meth:`pytket.backends.Backend.process_circuits`. - Supported kwargs: `seed`, `postprocess`, `seed_auto_increase`. - seed_auto_increase=True will automatically increase the seed by one for the - different batches when more than one circuit is submitted + Supported kwargs: `seed`, `postprocess`. """ circuits = list(circuits) n_shots_list = Backend._get_n_shots_as_list( @@ -289,7 +287,7 @@ def process_circuits( seed_simulator=seed, noise_model=self._noise_model, ) - if kwargs.get("seed_auto_increase") and type(seed) is int: + if type(seed) is int: seed += 1 jobid = job.job_id() for i, ind in enumerate(indices): diff --git a/pytket/extensions/qiskit/backends/ibmq_emulator.py b/pytket/extensions/qiskit/backends/ibmq_emulator.py index f74709fa..540a4b88 100644 --- a/pytket/extensions/qiskit/backends/ibmq_emulator.py +++ b/pytket/extensions/qiskit/backends/ibmq_emulator.py @@ -129,9 +129,7 @@ def process_circuits( ) -> List[ResultHandle]: """ See :py:meth:`pytket.backends.Backend.process_circuits`. - Supported kwargs: `seed`, `postprocess`, `seed_auto_increase`. - seed_auto_increase=True will automatically increase the seed by one for the - different batches when more than one circuit is submitted + Supported kwargs: `seed`, `postprocess`. """ circuits = list(circuits) n_shots_list = Backend._get_n_shots_as_list( @@ -177,7 +175,7 @@ def process_circuits( options.execution.shots = n_shots options.simulator.noise_model = self._noise_model options.seed_simulator = seed - if kwargs.get("seed_auto_increase") and type(seed) is int: + if type(seed) is int: seed += 1 sampler = Sampler(session=self._session, options=options) job = sampler.run(circuits=qcs) From e9d06275edbc32d302f73fab551f19a73e5ee6f8 Mon Sep 17 00:00:00 2001 From: Melf Date: Wed, 8 Nov 2023 14:37:08 +0000 Subject: [PATCH 4/4] remove testcases, clean up changes not needed --- docs/changelog.rst | 2 +- pytket/extensions/qiskit/backends/aer.py | 2 +- pytket/extensions/qiskit/backends/ibm.py | 2 +- .../extensions/qiskit/backends/ibm_utils.py | 7 +-- .../qiskit/backends/ibmq_emulator.py | 2 +- tests/backend_test.py | 60 ------------------- 6 files changed, 5 insertions(+), 70 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 7248d698..3603260a 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,7 +9,7 @@ unreleased * Update qiskit-ibm-runtime version to 0.13.0. * Update qiskit-aer version to 0.13.0. * Introduce dependency on qiskit-algorithms. -* Seed given to ``process_circuits()`` will be automaticly incremented +* Seed given to ``process_circuits()`` will be automatically incremented for the different circuit batches submitted. 0.45.0 (October 2023) diff --git a/pytket/extensions/qiskit/backends/aer.py b/pytket/extensions/qiskit/backends/aer.py index f196ad22..dda67bb6 100644 --- a/pytket/extensions/qiskit/backends/aer.py +++ b/pytket/extensions/qiskit/backends/aer.py @@ -237,7 +237,7 @@ def process_circuits( circuits: Sequence[Circuit], n_shots: Union[None, int, Sequence[Optional[int]]] = None, valid_check: bool = True, - **kwargs: Union[bool, int, float, str, None], + **kwargs: KwargTypes, ) -> List[ResultHandle]: """ See :py:meth:`pytket.backends.Backend.process_circuits`. diff --git a/pytket/extensions/qiskit/backends/ibm.py b/pytket/extensions/qiskit/backends/ibm.py index b687bd1c..4d68e90e 100644 --- a/pytket/extensions/qiskit/backends/ibm.py +++ b/pytket/extensions/qiskit/backends/ibm.py @@ -443,7 +443,7 @@ def process_circuits( circuits: Sequence[Circuit], n_shots: Union[None, int, Sequence[Optional[int]]] = None, valid_check: bool = True, - **kwargs: Union[bool, int, float, str, None], + **kwargs: KwargTypes, ) -> List[ResultHandle]: """ See :py:meth:`pytket.backends.Backend.process_circuits`. diff --git a/pytket/extensions/qiskit/backends/ibm_utils.py b/pytket/extensions/qiskit/backends/ibm_utils.py index 6ade4566..7a206727 100644 --- a/pytket/extensions/qiskit/backends/ibm_utils.py +++ b/pytket/extensions/qiskit/backends/ibm_utils.py @@ -16,7 +16,7 @@ """ import itertools -from typing import Collection, Optional, Sequence, Tuple, List, TYPE_CHECKING, Union +from typing import Collection, Optional, Sequence, Tuple, List, TYPE_CHECKING import numpy as np @@ -52,14 +52,10 @@ def _batch_circuits( :param n_shots: Number of shots for each circuit. :type n_shots: Sequence[int] """ - - assert len(n_shots) == len(circuits) - # take care of None entries n_shots_int = list(map(lambda x: x if x is not None else -1, n_shots)) order: Collection[int] = np.argsort(n_shots_int) - batches: List[Tuple[Optional[int], List["Circuit"]]] = [ (n, [circuits[i] for i in indices]) for n, indices in itertools.groupby(order, key=lambda i: n_shots[i]) @@ -68,5 +64,4 @@ def _batch_circuits( list(indices) for n, indices in itertools.groupby(order, key=lambda i: n_shots[i]) ] - return batches, batch_order diff --git a/pytket/extensions/qiskit/backends/ibmq_emulator.py b/pytket/extensions/qiskit/backends/ibmq_emulator.py index 540a4b88..accdf7a3 100644 --- a/pytket/extensions/qiskit/backends/ibmq_emulator.py +++ b/pytket/extensions/qiskit/backends/ibmq_emulator.py @@ -125,7 +125,7 @@ def process_circuits( circuits: Sequence[Circuit], n_shots: Union[None, int, Sequence[Optional[int]]] = None, valid_check: bool = True, - **kwargs: Union[bool, int, float, str, None], + **kwargs: KwargTypes, ) -> List[ResultHandle]: """ See :py:meth:`pytket.backends.Backend.process_circuits`. diff --git a/tests/backend_test.py b/tests/backend_test.py index 041ca660..e4bd91be 100644 --- a/tests/backend_test.py +++ b/tests/backend_test.py @@ -462,66 +462,6 @@ def test_nshots_batching(perth_backend: IBMQBackend) -> None: backend._MACHINE_DEBUG = False -@pytest.mark.skipif(skip_remote_tests, reason=REASON) -def test_nshots_nseeds_batching(perth_backend: IBMQBackend) -> None: - backend = perth_backend - backend._MACHINE_DEBUG = True - try: - c1 = Circuit(2, 2).H(0).CX(0, 1).measure_all() - c2 = Circuit(2, 2).Rx(0.5, 0).CX(0, 1).measure_all() - c3 = Circuit(2, 2).H(1).CX(0, 1).measure_all() - c4 = Circuit(2, 2).Rx(0.5, 0).CX(0, 1).CX(1, 0).measure_all() - cs = [c1, c2, c3, c4] - n_shots = [10, 12, 10, 13] - cs = backend.get_compiled_circuits(cs) - handles = backend.process_circuits( - cs, n_shots=n_shots, seed=10, seed_auto_increase=False - ) - - from pytket.extensions.qiskit.backends.ibm import _DEBUG_HANDLE_PREFIX - - assert all( - cast(str, hand[0]) == _DEBUG_HANDLE_PREFIX + suffix - for hand, suffix in zip( - handles, - [f"{(10, 0)}", f"{(12, 1)}", f"{(10, 0)}", f"{(13, 2)}"], - ) - ) - finally: - # ensure shared backend is reset for other tests - backend._MACHINE_DEBUG = False - - -@pytest.mark.skipif(skip_remote_tests, reason=REASON) -def test_nshots_nseeds_batching_ii(perth_backend: IBMQBackend) -> None: - backend = perth_backend - backend._MACHINE_DEBUG = True - try: - c1 = Circuit(2, 2).H(0).CX(0, 1).measure_all() - c2 = Circuit(2, 2).Rx(0.5, 0).CX(0, 1).measure_all() - c3 = Circuit(2, 2).H(1).CX(0, 1).measure_all() - c4 = Circuit(2, 2).Rx(0.5, 0).CX(0, 1).CX(1, 0).measure_all() - cs = [c1, c2, c3, c4] - n_shots = [10, 12, 10, 13] - cs = backend.get_compiled_circuits(cs) - handles = backend.process_circuits( - cs, n_shots=n_shots, seed=10, seed_auto_increase=True - ) - - from pytket.extensions.qiskit.backends.ibm import _DEBUG_HANDLE_PREFIX - - assert all( - cast(str, hand[0]) == _DEBUG_HANDLE_PREFIX + suffix - for hand, suffix in zip( - handles, - [f"{(10, 0)}", f"{(12, 1)}", f"{(10, 0)}", f"{(13, 2)}"], - ) - ) - finally: - # ensure shared backend is reset for other tests - backend._MACHINE_DEBUG = False - - @pytest.mark.flaky(reruns=3, reruns_delay=10) @pytest.mark.skipif(skip_remote_tests, reason=REASON) def test_nshots(perth_emulator_backend: IBMQEmulatorBackend) -> None: