From fda276edef33c1f5649713ddf3d3a39fef18895b Mon Sep 17 00:00:00 2001 From: Irfan Khan Date: Fri, 5 Apr 2024 16:27:39 +0100 Subject: [PATCH 1/7] specify qiskit API options in backend._process_circuits --- pytket/extensions/qiskit/backends/ibm.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/pytket/extensions/qiskit/backends/ibm.py b/pytket/extensions/qiskit/backends/ibm.py index 1970559f..29766e6c 100644 --- a/pytket/extensions/qiskit/backends/ibm.py +++ b/pytket/extensions/qiskit/backends/ibm.py @@ -462,7 +462,14 @@ def process_circuits( apply the pytket ``SimplifyInitial`` pass to improve fidelity of results assuming all qubits initialized to zero (bool, default False) - + * `options`: + Specify `resilience_level` and `optimization_level` + within a dictionary. This enables application of + error-mitigation and remote transpilation of circuits on + IBMQ Cloud. Values for `resilience_level` can be found + here: https://docs.quantum.ibm.com/run/configure-error-mitigation. + Values for `optimization_level` can be found here: + https://docs.quantum.ibm.com/run/configure-runtime-compilation """ circuits = list(circuits) @@ -478,6 +485,8 @@ def process_circuits( postprocess = kwargs.get("postprocess", False) simplify_initial = kwargs.get("simplify_initial", False) + options_dict = kwargs.get("options", {}) + batch_id = 0 # identify batches for debug purposes only for (n_shots, batch), indices in zip(circuit_batches, batch_order): for chunk in itertools.zip_longest( @@ -511,7 +520,10 @@ def process_circuits( ppcirc_strs[i], ) else: - options = Options() + options = Options( + optimization_level=options_dict.get("optimization_level", 0), + resilience_level=options_dict.get("resilience_level", 0) + ) options.optimization_level = 0 options.resilience_level = 0 options.transpilation.skip_transpilation = True From 86ec400ae97ae6bde0cb07d0d1bee5ab0e6356b5 Mon Sep 17 00:00:00 2001 From: Irfan Khan Date: Fri, 5 Apr 2024 16:33:43 +0100 Subject: [PATCH 2/7] qiskit api options can be passed to IBMQBackend during construction --- pytket/extensions/qiskit/backends/ibm.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pytket/extensions/qiskit/backends/ibm.py b/pytket/extensions/qiskit/backends/ibm.py index 29766e6c..d48d1b49 100644 --- a/pytket/extensions/qiskit/backends/ibm.py +++ b/pytket/extensions/qiskit/backends/ibm.py @@ -167,6 +167,10 @@ class IBMQBackend(Backend): :type provider: Optional[IBMProvider] :param token: Authentication token to use the `QiskitRuntimeService`. :type token: Optional[str] + :param options: A dictionary to specify qiskit API options, + `resilience_level` and `optimization_level`. Passed to the qiskit + sampler submission during process_circuit (process_circuits). + :type options: Dict[str, int] """ _supports_shots = False @@ -181,6 +185,7 @@ def __init__( monitor: bool = True, provider: Optional["IBMProvider"] = None, token: Optional[str] = None, + options: Dict[str, int] = {} ): super().__init__() self._pytket_config = QiskitConfig.from_default_config_file() @@ -210,6 +215,8 @@ def __init__( # cache of results keyed by job id and circuit index self._ibm_res_cache: Dict[Tuple[str, int], Counter] = dict() + self._sampler_options = options + self._MACHINE_DEBUG = False @staticmethod @@ -486,6 +493,8 @@ def process_circuits( simplify_initial = kwargs.get("simplify_initial", False) options_dict = kwargs.get("options", {}) + if not bool(options_dict): + options_dict = self._sampler_options batch_id = 0 # identify batches for debug purposes only for (n_shots, batch), indices in zip(circuit_batches, batch_order): From 6b839fba72cbd244b15eb80fa98441a8d29fc455 Mon Sep 17 00:00:00 2001 From: Irfan Khan Date: Fri, 5 Apr 2024 16:38:46 +0100 Subject: [PATCH 3/7] lint --- pytket/extensions/qiskit/backends/ibm.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/pytket/extensions/qiskit/backends/ibm.py b/pytket/extensions/qiskit/backends/ibm.py index d48d1b49..a9a5c5e3 100644 --- a/pytket/extensions/qiskit/backends/ibm.py +++ b/pytket/extensions/qiskit/backends/ibm.py @@ -167,8 +167,8 @@ class IBMQBackend(Backend): :type provider: Optional[IBMProvider] :param token: Authentication token to use the `QiskitRuntimeService`. :type token: Optional[str] - :param options: A dictionary to specify qiskit API options, - `resilience_level` and `optimization_level`. Passed to the qiskit + :param options: A dictionary to specify qiskit API options, + `resilience_level` and `optimization_level`. Passed to the qiskit sampler submission during process_circuit (process_circuits). :type options: Dict[str, int] """ @@ -185,7 +185,7 @@ def __init__( monitor: bool = True, provider: Optional["IBMProvider"] = None, token: Optional[str] = None, - options: Dict[str, int] = {} + options: Dict[str, int] = None, ): super().__init__() self._pytket_config = QiskitConfig.from_default_config_file() @@ -215,6 +215,8 @@ def __init__( # cache of results keyed by job id and circuit index self._ibm_res_cache: Dict[Tuple[str, int], Counter] = dict() + if options is None: + options = {"optimization_level": 0, "resilience_level": 0} self._sampler_options = options self._MACHINE_DEBUG = False @@ -470,12 +472,12 @@ def process_circuits( fidelity of results assuming all qubits initialized to zero (bool, default False) * `options`: - Specify `resilience_level` and `optimization_level` - within a dictionary. This enables application of - error-mitigation and remote transpilation of circuits on - IBMQ Cloud. Values for `resilience_level` can be found + Specify `resilience_level` and `optimization_level` + within a dictionary. This enables application of + error-mitigation and remote transpilation of circuits on + IBMQ Cloud. Values for `resilience_level` can be found here: https://docs.quantum.ibm.com/run/configure-error-mitigation. - Values for `optimization_level` can be found here: + Values for `optimization_level` can be found here: https://docs.quantum.ibm.com/run/configure-runtime-compilation """ circuits = list(circuits) @@ -494,7 +496,7 @@ def process_circuits( options_dict = kwargs.get("options", {}) if not bool(options_dict): - options_dict = self._sampler_options + options_dict = self._sampler_options batch_id = 0 # identify batches for debug purposes only for (n_shots, batch), indices in zip(circuit_batches, batch_order): @@ -531,7 +533,7 @@ def process_circuits( else: options = Options( optimization_level=options_dict.get("optimization_level", 0), - resilience_level=options_dict.get("resilience_level", 0) + resilience_level=options_dict.get("resilience_level", 0), ) options.optimization_level = 0 options.resilience_level = 0 From 0a238c223558c1acb84c89c73feef6e25c5c38af Mon Sep 17 00:00:00 2001 From: Irfan Khan Date: Wed, 17 Apr 2024 14:43:19 +0100 Subject: [PATCH 4/7] pass options as Options instance rather than dict and define default values for options in constructor if kwarg not passed. --- pytket/extensions/qiskit/backends/ibm.py | 34 +++++++++++------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/pytket/extensions/qiskit/backends/ibm.py b/pytket/extensions/qiskit/backends/ibm.py index a9a5c5e3..a20db63f 100644 --- a/pytket/extensions/qiskit/backends/ibm.py +++ b/pytket/extensions/qiskit/backends/ibm.py @@ -167,9 +167,12 @@ class IBMQBackend(Backend): :type provider: Optional[IBMProvider] :param token: Authentication token to use the `QiskitRuntimeService`. :type token: Optional[str] - :param options: A dictionary to specify qiskit API options, - `resilience_level` and `optimization_level`. Passed to the qiskit - sampler submission during process_circuit (process_circuits). + :param options: A customised `qiskit_ibm_runtime` `Options` instance. + Passed to the qiskit sampler submission during + `process_circuit` (`process_circuits`). If the `Options` instance is not + specified, both `optimization_level` and `resilience_level` are set to 0, + and `skip_transpilation` is set to True. These default values can be customised + by using the `options` keyword argument. :type options: Dict[str, int] """ @@ -185,7 +188,7 @@ def __init__( monitor: bool = True, provider: Optional["IBMProvider"] = None, token: Optional[str] = None, - options: Dict[str, int] = None, + options: Options = None, ): super().__init__() self._pytket_config = QiskitConfig.from_default_config_file() @@ -216,7 +219,10 @@ def __init__( self._ibm_res_cache: Dict[Tuple[str, int], Counter] = dict() if options is None: - options = {"optimization_level": 0, "resilience_level": 0} + options = Options() + options.optimization_level = 0 + options.resilience_level = 0 + options.transpilation.skip_transpilation = True self._sampler_options = options self._MACHINE_DEBUG = False @@ -472,8 +478,7 @@ def process_circuits( fidelity of results assuming all qubits initialized to zero (bool, default False) * `options`: - Specify `resilience_level` and `optimization_level` - within a dictionary. This enables application of + Use a custom qiskit Options instance. This enables application of error-mitigation and remote transpilation of circuits on IBMQ Cloud. Values for `resilience_level` can be found here: https://docs.quantum.ibm.com/run/configure-error-mitigation. @@ -494,9 +499,10 @@ def process_circuits( postprocess = kwargs.get("postprocess", False) simplify_initial = kwargs.get("simplify_initial", False) - options_dict = kwargs.get("options", {}) - if not bool(options_dict): - options_dict = self._sampler_options + options: Options = kwargs.get("options") + if options is None: + options = self._sampler_options + options.execution.shots = n_shots batch_id = 0 # identify batches for debug purposes only for (n_shots, batch), indices in zip(circuit_batches, batch_order): @@ -531,14 +537,6 @@ def process_circuits( ppcirc_strs[i], ) else: - options = Options( - optimization_level=options_dict.get("optimization_level", 0), - resilience_level=options_dict.get("resilience_level", 0), - ) - options.optimization_level = 0 - options.resilience_level = 0 - options.transpilation.skip_transpilation = True - options.execution.shots = n_shots sampler = Sampler(session=self._session, options=options) job = sampler.run( circuits=qcs, From 747fba51ca4eecd1d02d24ae9a0529baba91d3ea Mon Sep 17 00:00:00 2001 From: Irfan Khan Date: Mon, 22 Apr 2024 12:11:26 +0100 Subject: [PATCH 5/7] set number of shots as qiskit option per chunk in batch --- pytket/extensions/qiskit/backends/ibm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytket/extensions/qiskit/backends/ibm.py b/pytket/extensions/qiskit/backends/ibm.py index 1853fb10..b80d7c97 100644 --- a/pytket/extensions/qiskit/backends/ibm.py +++ b/pytket/extensions/qiskit/backends/ibm.py @@ -543,7 +543,6 @@ def process_circuits( options: Options = kwargs.get("options") if options is None: options = self._sampler_options - options.execution.shots = n_shots batch_id = 0 # identify batches for debug purposes only for (n_shots, batch), indices in zip(circuit_batches, batch_order): @@ -578,6 +577,7 @@ def process_circuits( ppcirc_strs[i], ) else: + options.execution.shots = n_shots sampler = Sampler(session=self._session, options=options) job = sampler.run( circuits=qcs, From 54fab461bf7e691f321825e6bf8550a7d83e14c5 Mon Sep 17 00:00:00 2001 From: Irfan Khan Date: Mon, 22 Apr 2024 13:50:24 +0100 Subject: [PATCH 6/7] update changelog --- docs/changelog.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 51924a1f..39f7176b 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,13 @@ Changelog ~~~~~~~~~ +Unreleased +---------- + +* User can pass an `Options` instance (from `qiskit-ibm-runtime`) +via a keyword argument to both an `IBMQBackend` constructor and +an instance method `IBMQBackend.process_circuits`. + 0.53.0 (April 2024) ------------------- From 104343dea5eb465b06c2cfde42ecf4d2a2a85bc5 Mon Sep 17 00:00:00 2001 From: Alec Edgington <54802828+cqc-alec@users.noreply.github.com> Date: Mon, 22 Apr 2024 14:06:53 +0100 Subject: [PATCH 7/7] Update docs/changelog.rst --- docs/changelog.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 39f7176b..b037640f 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,8 +5,8 @@ Unreleased ---------- * User can pass an `Options` instance (from `qiskit-ibm-runtime`) -via a keyword argument to both an `IBMQBackend` constructor and -an instance method `IBMQBackend.process_circuits`. + via a keyword argument to both an `IBMQBackend` constructor and + an instance method `IBMQBackend.process_circuits`. 0.53.0 (April 2024) -------------------