From 2eef25da80bdb7389c1b45da0f6d40b73c5fb87c Mon Sep 17 00:00:00 2001 From: Zachary Schoenfeld Date: Wed, 9 Jun 2021 08:40:22 -0400 Subject: [PATCH 1/5] Add tests for esp support --- qiskit/compiler/assembler.py | 21 +++++++++++++-- qiskit/execute_function.py | 8 ++++++ .../providers/models/backendconfiguration.py | 8 ++++++ .../schemas/backend_configuration_schema.json | 5 ++++ test/python/compiler/test_assembler.py | 27 +++++++++++++++++++ 5 files changed, 67 insertions(+), 2 deletions(-) diff --git a/qiskit/compiler/assembler.py b/qiskit/compiler/assembler.py index 537cff92b1c0..0f5c1bcfcc17 100644 --- a/qiskit/compiler/assembler.py +++ b/qiskit/compiler/assembler.py @@ -74,7 +74,8 @@ def assemble( rep_delay: Optional[float] = None, parameter_binds: Optional[List[Dict[Parameter, float]]] = None, parametric_pulses: Optional[List[str]] = None, - init_qubits: bool = True, + init_qubits: Optional[bool] = True, + use_measure_esp: Optional[bool] = None, **run_config: Dict, ) -> Qobj: """Assemble a list of circuits or pulse schedules into a ``Qobj``. @@ -140,7 +141,11 @@ def assemble( ['gaussian', 'constant'] init_qubits: Whether to reset the qubits to the ground state for each shot. - Default: ``True``. + Default: ``True``. + use_measure_esp: Whether to use ESP (excited state promoted) readout for the final + measurement in each circuit. ESP readout can offer higher fidelity than standard + measurement sequences. See `here `_. + Default (set on backend): ``True`` if backend supports ESP readout, else ``False``. **run_config: Extra arguments used to configure the run (e.g., for Aer configurable backends). Refer to the backend documentation for details on these arguments. @@ -163,6 +168,7 @@ def assemble( max_credits, seed_simulator, init_qubits, + use_measure_esp, rep_delay, qubit_lo_freq, meas_lo_freq, @@ -230,6 +236,7 @@ def _parse_common_args( max_credits, seed_simulator, init_qubits, + use_measure_esp, rep_delay, qubit_lo_freq, meas_lo_freq, @@ -258,6 +265,8 @@ def _parse_common_args( - If any of qubit or meas lo's, or associated ranges do not have length equal to ``n_qubits``. - If qubit or meas lo's do not fit into perscribed ranges. + - If ``use_measure_esp`` is set to ``True`` on a device which does not support ESP + readout. """ # grab relevant info from backend if it exists backend_config = None @@ -343,6 +352,13 @@ def _parse_common_args( for lo_config in schedule_los ] + measure_esp_enabled = getattr(backend_config, "measure_esp_enabled", False) + if use_measure_esp is None: + use_measure_esp = True if measure_esp_enabled else False # default use of esp readout + if not measure_esp_enabled and use_measure_esp: + raise QiskitError("ESP readout not supported on this device. Please make sure the flag " + "'use_measure_esp' is set to 'False' or not used.") + # create run configuration and populate run_config_dict = dict( shots=shots, @@ -350,6 +366,7 @@ def _parse_common_args( max_credits=max_credits, seed_simulator=seed_simulator, init_qubits=init_qubits, + use_measure_esp=use_measure_esp, rep_delay=rep_delay, qubit_lo_freq=qubit_lo_freq, meas_lo_freq=meas_lo_freq, diff --git a/qiskit/execute_function.py b/qiskit/execute_function.py index aea9daef4c4d..07b0bcfa98a9 100644 --- a/qiskit/execute_function.py +++ b/qiskit/execute_function.py @@ -69,6 +69,7 @@ def execute( meas_map=None, scheduling_method=None, init_qubits=None, + use_measure_esp=None, **run_config, ): """Execute a list of :class:`qiskit.circuit.QuantumCircuit` or @@ -244,6 +245,11 @@ def execute( init_qubits (bool): Whether to reset the qubits to the ground state for each shot. Default: ``True``. + use_measure_esp (bool): Whether to use ESP (excited state promoted) readout for the final + measurement in each circuit. ESP readout can offer higher fidelity than standard + measurement sequences. See `here `_. + Default (set on backend): ``True`` if backend supports ESP readout, else ``False``. + run_config (dict): Extra arguments used to configure the run (e.g. for Aer configurable backends). Refer to the backend documentation for details on these arguments. @@ -346,6 +352,7 @@ def execute( parameter_binds=parameter_binds, backend=backend, init_qubits=init_qubits, + use_measure_esp=use_measure_esp, **run_config, ) @@ -372,6 +379,7 @@ def execute( "rep_time": rep_time, "rep_delay": rep_delay, "init_qubits": init_qubits, + "use_measure_esp": use_measure_esp, } for key in list(run_kwargs.keys()): if not hasattr(backend.options, key): diff --git a/qiskit/providers/models/backendconfiguration.py b/qiskit/providers/models/backendconfiguration.py index 20221d9ecbc5..d661dad09b0c 100644 --- a/qiskit/providers/models/backendconfiguration.py +++ b/qiskit/providers/models/backendconfiguration.py @@ -245,6 +245,7 @@ def __init__( dtm=None, processor_type=None, parametric_pulses=None, + measure_esp_enabled=False, **kwargs, ): """Initialize a QasmBackendConfiguration Object @@ -300,6 +301,10 @@ def __init__( - segment: Segment this processor belongs to within a larger chip. parametric_pulses (list): A list of pulse shapes which are supported on the backend. For example: ``['gaussian', 'constant']`` + measure_esp_enabled (bool): Whether ESP readout is enabled on this device. ESP readout + discriminates between the |0> and higher transmon states so as to produce increased + readout fidelity. See `here `_. Defaults to + ``False``. **kwargs: optional fields """ @@ -360,6 +365,8 @@ def __init__( if parametric_pulses is not None: self.parametric_pulses = parametric_pulses + self.measure_esp_enabled = measure_esp_enabled + # convert lo range from GHz to Hz if "qubit_lo_range" in kwargs.keys(): kwargs["qubit_lo_range"] = [ @@ -421,6 +428,7 @@ def to_dict(self): "max_shots": self.max_shots, "coupling_map": self.coupling_map, "dynamic_reprate_enabled": self.dynamic_reprate_enabled, + "measure_esp_enabled": self.measure_esp_enabled, } if hasattr(self, "supported_instructions"): diff --git a/qiskit/schemas/backend_configuration_schema.json b/qiskit/schemas/backend_configuration_schema.json index 0b2deb698a99..25a41c730d1c 100644 --- a/qiskit/schemas/backend_configuration_schema.json +++ b/qiskit/schemas/backend_configuration_schema.json @@ -157,6 +157,11 @@ "description": "Whether delay between programs can be set dynamically using 'rep_delay').", "default": false }, + "measure_esp_enabled": { + "type": "boolean", + "description": "Whether ESP readout is supported by the backend.", + "default": false + }, "supported_instructions": { "type": "array", "minItems": 0, diff --git a/test/python/compiler/test_assembler.py b/test/python/compiler/test_assembler.py index 99d71821dc0d..ab0d9ff19665 100644 --- a/test/python/compiler/test_assembler.py +++ b/test/python/compiler/test_assembler.py @@ -471,6 +471,33 @@ def test_init_qubits_false(self): qobj = assemble(self.circ, init_qubits=False) self.assertEqual(qobj.config.init_qubits, False) + def test_measure_esp_not_enabled(self): + """Check that an error is raised if ``use_measure_esp=True`` on a device which does not + support ESP readout.""" + setattr(self.backend_config, "measure_esp_enabled", False) + with self.assertRaises(QiskitError): + assemble(self.circ, self.backend, use_measure_esp=True) + + def test_measure_esp_defaults(self): + """Check that ``use_measure_esp`` defaults to True if ESP readout is enabled on the device + and false otherwise.""" + # esp readout enabled + setattr(self.backend_config, "measure_esp_enabled", True) + qobj = assemble(self.circ, self.backend) + self.assertEqual(qobj.config.use_measure_esp, True) + + # esp readout not enabled + setattr(self.backend_config, "measure_esp_enabled", False) + qobj = assemble(self.circ, self.backend) + self.assertEqual(qobj.config.use_measure_esp, False) + + def test_measure_esp(self): + """Test that ``use_measure_esp=True`` works on a device that supports ESP readout.""" + # esp readout enabled + setattr(self.backend_config, "measure_esp_enabled", True) + qobj = assemble(self.circ, self.backend, use_measure_esp=True) + self.assertEqual(qobj.config.use_measure_esp, True) + def test_circuit_with_global_phase(self): """Test that global phase for a circuit is handled correctly.""" circ = QuantumCircuit(2) From df3c974d89e6e5e75b41f702977276818d1aeae6 Mon Sep 17 00:00:00 2001 From: Zachary Schoenfeld Date: Wed, 9 Jun 2021 08:49:00 -0400 Subject: [PATCH 2/5] Add reno note --- .../notes/esp-readout-3aa5fff772ddbab1.yaml | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 releasenotes/notes/esp-readout-3aa5fff772ddbab1.yaml diff --git a/releasenotes/notes/esp-readout-3aa5fff772ddbab1.yaml b/releasenotes/notes/esp-readout-3aa5fff772ddbab1.yaml new file mode 100644 index 000000000000..bd6c0477e60b --- /dev/null +++ b/releasenotes/notes/esp-readout-3aa5fff772ddbab1.yaml @@ -0,0 +1,24 @@ +--- +features: + - | + Support for Excited State Promoted (ESP) readout from Qiskit has been added. ESP readout + discriminates between |0> and higher order energy states of transmon qubits in order to improve + readout fidelity. Further details may be found `here `_. + + To check whether the backend supports ESP readout, one can query:: + + measure_esp_enabled = getattr(backend.configuration(), "measure_esp_enabled", False) + + If the flag ``measure_esp_enabled`` is not in the backend configuration, we return ``False`` + by default. + + A user can request usage of ESP readout via the ``use_measure_esp`` flag in + ``execute/assemble``. This tells the backend to use ESP readout on the final measurement of + each circuit. This is done via:: + + qobj = assemble(circ, backend, use_measure_esp=True) + + If ``measure_esp_enabled=False`` and ``use_measure_esp=True``, a ``QiskitError`` is raised. + + If ``use_measure_esp`` is not set, it will default to True if ``measure_esp_enabled=True``, + otherwise ``False``. From de6d6073315d5607ef59c929861b38aa6d47847a Mon Sep 17 00:00:00 2001 From: Zachary Schoenfeld Date: Thu, 10 Jun 2021 11:12:53 -0400 Subject: [PATCH 3/5] Fix comments and run black --- qiskit/compiler/assembler.py | 20 ++++++++++--------- .../providers/models/backendconfiguration.py | 9 ++++----- .../schemas/backend_configuration_schema.json | 2 +- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/qiskit/compiler/assembler.py b/qiskit/compiler/assembler.py index 0f5c1bcfcc17..451d5251ffe6 100644 --- a/qiskit/compiler/assembler.py +++ b/qiskit/compiler/assembler.py @@ -142,10 +142,11 @@ def assemble( ['gaussian', 'constant'] init_qubits: Whether to reset the qubits to the ground state for each shot. Default: ``True``. - use_measure_esp: Whether to use ESP (excited state promoted) readout for the final - measurement in each circuit. ESP readout can offer higher fidelity than standard - measurement sequences. See `here `_. - Default (set on backend): ``True`` if backend supports ESP readout, else ``False``. + use_measure_esp: Whether to use excited state promoted (ESP) readout for the final + measurement in each circuit. ESP readout discriminates between the |0> and higher + transmon states to improve readout fidelity. See + `here `_. + Default: ``True`` if the backend supports ESP readout, else ``False``. **run_config: Extra arguments used to configure the run (e.g., for Aer configurable backends). Refer to the backend documentation for details on these arguments. @@ -353,11 +354,12 @@ def _parse_common_args( ] measure_esp_enabled = getattr(backend_config, "measure_esp_enabled", False) - if use_measure_esp is None: - use_measure_esp = True if measure_esp_enabled else False # default use of esp readout - if not measure_esp_enabled and use_measure_esp: - raise QiskitError("ESP readout not supported on this device. Please make sure the flag " - "'use_measure_esp' is set to 'False' or not used.") + use_measure_esp = use_measure_esp or measure_esp_enabled # default to backend support value + if use_measure_esp and not measure_esp_enabled: + raise QiskitError( + "ESP readout not supported on this device. Please make sure the flag " + "'use_measure_esp' is unset or set to 'False'." + ) # create run configuration and populate run_config_dict = dict( diff --git a/qiskit/providers/models/backendconfiguration.py b/qiskit/providers/models/backendconfiguration.py index d661dad09b0c..629bab617904 100644 --- a/qiskit/providers/models/backendconfiguration.py +++ b/qiskit/providers/models/backendconfiguration.py @@ -301,11 +301,10 @@ def __init__( - segment: Segment this processor belongs to within a larger chip. parametric_pulses (list): A list of pulse shapes which are supported on the backend. For example: ``['gaussian', 'constant']`` - measure_esp_enabled (bool): Whether ESP readout is enabled on this device. ESP readout - discriminates between the |0> and higher transmon states so as to produce increased - readout fidelity. See `here `_. Defaults to - ``False``. - + measure_esp_enabled (bool): Whether excited state promoted (ESP) readout is enabled on + this device. ESP readout discriminates between the |0> and higher transmon states to + improve readout fidelity. See `here `_. + Default: ``False``. **kwargs: optional fields """ self._data = {} diff --git a/qiskit/schemas/backend_configuration_schema.json b/qiskit/schemas/backend_configuration_schema.json index 25a41c730d1c..884da310548e 100644 --- a/qiskit/schemas/backend_configuration_schema.json +++ b/qiskit/schemas/backend_configuration_schema.json @@ -2,7 +2,7 @@ "$schema": "http://json-schema.org/draft-04/schema#", "id": "http://www.qiskit.org/schemas/backend_config_schema.json", "description": "Qiskit device backend configuration", - "version": "1.4.3", + "version": "1.4.4", "definitions": { "hamiltonian": { "type": "object", From c0ff08cd0d6407a6ec3b9d8f10f746b09f4a0e44 Mon Sep 17 00:00:00 2001 From: Zachary Schoenfeld Date: Fri, 11 Jun 2021 17:30:36 -0400 Subject: [PATCH 4/5] Update docs --- qiskit/compiler/assembler.py | 4 ++-- qiskit/execute_function.py | 5 +++-- .../providers/models/backendconfiguration.py | 6 +++--- .../notes/esp-readout-3aa5fff772ddbab1.yaml | 19 +++++++++---------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/qiskit/compiler/assembler.py b/qiskit/compiler/assembler.py index 451d5251ffe6..14988c55ee5a 100644 --- a/qiskit/compiler/assembler.py +++ b/qiskit/compiler/assembler.py @@ -74,7 +74,7 @@ def assemble( rep_delay: Optional[float] = None, parameter_binds: Optional[List[Dict[Parameter, float]]] = None, parametric_pulses: Optional[List[str]] = None, - init_qubits: Optional[bool] = True, + init_qubits: bool = True, use_measure_esp: Optional[bool] = None, **run_config: Dict, ) -> Qobj: @@ -143,7 +143,7 @@ def assemble( init_qubits: Whether to reset the qubits to the ground state for each shot. Default: ``True``. use_measure_esp: Whether to use excited state promoted (ESP) readout for the final - measurement in each circuit. ESP readout discriminates between the |0> and higher + measurement in each circuit. ESP readout discriminates between the ``|0>`` and higher transmon states to improve readout fidelity. See `here `_. Default: ``True`` if the backend supports ESP readout, else ``False``. diff --git a/qiskit/execute_function.py b/qiskit/execute_function.py index 07b0bcfa98a9..07ce487d8872 100644 --- a/qiskit/execute_function.py +++ b/qiskit/execute_function.py @@ -243,12 +243,13 @@ def execute( Optionally specify a particular scheduling method. init_qubits (bool): Whether to reset the qubits to the ground state for each shot. - Default: ``True``. + Default: ``True``. use_measure_esp (bool): Whether to use ESP (excited state promoted) readout for the final measurement in each circuit. ESP readout can offer higher fidelity than standard measurement sequences. See `here `_. - Default (set on backend): ``True`` if backend supports ESP readout, else ``False``. + Default: Value of ``measure_esp_enabled``, which reflects whether ESP readout is + supported by the backend. run_config (dict): Extra arguments used to configure the run (e.g. for Aer configurable backends). diff --git a/qiskit/providers/models/backendconfiguration.py b/qiskit/providers/models/backendconfiguration.py index 629bab617904..d5af35603793 100644 --- a/qiskit/providers/models/backendconfiguration.py +++ b/qiskit/providers/models/backendconfiguration.py @@ -302,9 +302,9 @@ def __init__( parametric_pulses (list): A list of pulse shapes which are supported on the backend. For example: ``['gaussian', 'constant']`` measure_esp_enabled (bool): Whether excited state promoted (ESP) readout is enabled on - this device. ESP readout discriminates between the |0> and higher transmon states to - improve readout fidelity. See `here `_. - Default: ``False``. + this device. ESP readout discriminates between the ``|0>`` and higher transmon + states to improve readout fidelity. See + `here `_. Defaults to ``False``. **kwargs: optional fields """ self._data = {} diff --git a/releasenotes/notes/esp-readout-3aa5fff772ddbab1.yaml b/releasenotes/notes/esp-readout-3aa5fff772ddbab1.yaml index bd6c0477e60b..9a5bb4d5be9e 100644 --- a/releasenotes/notes/esp-readout-3aa5fff772ddbab1.yaml +++ b/releasenotes/notes/esp-readout-3aa5fff772ddbab1.yaml @@ -2,23 +2,22 @@ features: - | Support for Excited State Promoted (ESP) readout from Qiskit has been added. ESP readout - discriminates between |0> and higher order energy states of transmon qubits in order to improve - readout fidelity. Further details may be found `here `_. + discriminates between ``|0>`` and higher order energy states of transmon qubits in order to + improve readout fidelity. Further details may be found + `here `_. To check whether the backend supports ESP readout, one can query:: - measure_esp_enabled = getattr(backend.configuration(), "measure_esp_enabled", False) + measure_esp_enabled = getattr(backend.configuration(), "measure_esp_enabled", False) If the flag ``measure_esp_enabled`` is not in the backend configuration, we return ``False`` by default. A user can request usage of ESP readout via the ``use_measure_esp`` flag in - ``execute/assemble``. This tells the backend to use ESP readout on the final measurement of - each circuit. This is done via:: + :meth:`~qiskit.execute_function.execute` or :meth:`~qiskit.compiler.assemble`. This tells the + backend to use ESP readout on the final measurement of each circuit. This is done via:: - qobj = assemble(circ, backend, use_measure_esp=True) + qobj = assemble(circ, backend, use_measure_esp=True) - If ``measure_esp_enabled=False`` and ``use_measure_esp=True``, a ``QiskitError`` is raised. - - If ``use_measure_esp`` is not set, it will default to True if ``measure_esp_enabled=True``, - otherwise ``False``. + If ``measure_esp_enabled=False`` and ``use_measure_esp=True``, a ``QiskitError`` is raised. If + ``use_measure_esp`` is not set, it will default to the value of ``measure_esp_enabled``. From 9af1534eb4eb37589a5ecef10a0521ff0d3ecc86 Mon Sep 17 00:00:00 2001 From: Zachary Schoenfeld Date: Mon, 14 Jun 2021 09:33:44 -0400 Subject: [PATCH 5/5] Remove explicit use_measure_esp from execute --- qiskit/execute_function.py | 9 --------- releasenotes/notes/esp-readout-3aa5fff772ddbab1.yaml | 4 ++-- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/qiskit/execute_function.py b/qiskit/execute_function.py index 07ce487d8872..d090ab1811c2 100644 --- a/qiskit/execute_function.py +++ b/qiskit/execute_function.py @@ -69,7 +69,6 @@ def execute( meas_map=None, scheduling_method=None, init_qubits=None, - use_measure_esp=None, **run_config, ): """Execute a list of :class:`qiskit.circuit.QuantumCircuit` or @@ -245,12 +244,6 @@ def execute( init_qubits (bool): Whether to reset the qubits to the ground state for each shot. Default: ``True``. - use_measure_esp (bool): Whether to use ESP (excited state promoted) readout for the final - measurement in each circuit. ESP readout can offer higher fidelity than standard - measurement sequences. See `here `_. - Default: Value of ``measure_esp_enabled``, which reflects whether ESP readout is - supported by the backend. - run_config (dict): Extra arguments used to configure the run (e.g. for Aer configurable backends). Refer to the backend documentation for details on these arguments. @@ -353,7 +346,6 @@ def execute( parameter_binds=parameter_binds, backend=backend, init_qubits=init_qubits, - use_measure_esp=use_measure_esp, **run_config, ) @@ -380,7 +372,6 @@ def execute( "rep_time": rep_time, "rep_delay": rep_delay, "init_qubits": init_qubits, - "use_measure_esp": use_measure_esp, } for key in list(run_kwargs.keys()): if not hasattr(backend.options, key): diff --git a/releasenotes/notes/esp-readout-3aa5fff772ddbab1.yaml b/releasenotes/notes/esp-readout-3aa5fff772ddbab1.yaml index 9a5bb4d5be9e..c539976aa709 100644 --- a/releasenotes/notes/esp-readout-3aa5fff772ddbab1.yaml +++ b/releasenotes/notes/esp-readout-3aa5fff772ddbab1.yaml @@ -14,8 +14,8 @@ features: by default. A user can request usage of ESP readout via the ``use_measure_esp`` flag in - :meth:`~qiskit.execute_function.execute` or :meth:`~qiskit.compiler.assemble`. This tells the - backend to use ESP readout on the final measurement of each circuit. This is done via:: + :meth:`~qiskit.compiler.assemble`. This tells the backend to use ESP readout on the final + measurement of each circuit. This is done via:: qobj = assemble(circ, backend, use_measure_esp=True)