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

Add ESP readout support to Qiskit #6543

Merged
merged 9 commits into from
Jun 14, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions qiskit/compiler/assembler.py
Original file line number Diff line number Diff line change
Expand Up @@ -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``.
Expand Down Expand Up @@ -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
zachschoenfeld33 marked this conversation as resolved.
Show resolved Hide resolved
measurement in each circuit. ESP readout can offer higher fidelity than standard
measurement sequences. See `here <https://arxiv.org/pdf/2008.08571.pdf>`_.
Default (set on backend): ``True`` if backend supports ESP readout, else ``False``.
zachschoenfeld33 marked this conversation as resolved.
Show resolved Hide resolved
**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.
Expand All @@ -163,6 +168,7 @@ def assemble(
max_credits,
seed_simulator,
init_qubits,
use_measure_esp,
rep_delay,
qubit_lo_freq,
meas_lo_freq,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -343,13 +352,21 @@ 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.")
zachschoenfeld33 marked this conversation as resolved.
Show resolved Hide resolved

# create run configuration and populate
run_config_dict = dict(
shots=shots,
memory=memory,
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,
Expand Down
8 changes: 8 additions & 0 deletions qiskit/execute_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def execute(
meas_map=None,
scheduling_method=None,
init_qubits=None,
use_measure_esp=None,
zachschoenfeld33 marked this conversation as resolved.
Show resolved Hide resolved
**run_config,
):
"""Execute a list of :class:`qiskit.circuit.QuantumCircuit` or
Expand Down Expand Up @@ -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 <https://arxiv.org/pdf/2008.08571.pdf>`_.
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.
Expand Down Expand Up @@ -346,6 +352,7 @@ def execute(
parameter_binds=parameter_binds,
backend=backend,
init_qubits=init_qubits,
use_measure_esp=use_measure_esp,
**run_config,
)

Expand All @@ -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):
Expand Down
8 changes: 8 additions & 0 deletions qiskit/providers/models/backendconfiguration.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ def __init__(
dtm=None,
processor_type=None,
parametric_pulses=None,
measure_esp_enabled=False,
**kwargs,
):
"""Initialize a QasmBackendConfiguration Object
Expand Down Expand Up @@ -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
zachschoenfeld33 marked this conversation as resolved.
Show resolved Hide resolved
discriminates between the |0> and higher transmon states so as to produce increased
readout fidelity. See `here <https://arxiv.org/pdf/2008.08571.pdf>`_. Defaults to
``False``.

**kwargs: optional fields
"""
Expand Down Expand Up @@ -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"] = [
Expand Down Expand Up @@ -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"):
Expand Down
5 changes: 5 additions & 0 deletions qiskit/schemas/backend_configuration_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@
"description": "Whether delay between programs can be set dynamically using 'rep_delay').",
"default": false
},
"measure_esp_enabled": {
zachschoenfeld33 marked this conversation as resolved.
Show resolved Hide resolved
"type": "boolean",
"description": "Whether ESP readout is supported by the backend.",
"default": false
},
"supported_instructions": {
"type": "array",
"minItems": 0,
Expand Down
24 changes: 24 additions & 0 deletions releasenotes/notes/esp-readout-3aa5fff772ddbab1.yaml
Original file line number Diff line number Diff line change
@@ -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 <https://arxiv.org/pdf/2008.08571.pdf>`_.

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``.
27 changes: 27 additions & 0 deletions test/python/compiler/test_assembler.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down