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 readout error mitigated tomography experiments #1024

Merged
merged 5 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 8 additions & 1 deletion qiskit_experiments/library/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
~randomized_benchmarking.InterleavedRB
~tomography.StateTomography
~tomography.ProcessTomography
~tomography.MitigatedStateTomography
~tomography.MitigatedProcessTomography
~quantum_volume.QuantumVolume

.. _characterization:
Expand Down Expand Up @@ -156,7 +158,12 @@ class instance to manage parameters and pulse schedules.
MultiStateDiscrimination,
)
from .randomized_benchmarking import StandardRB, InterleavedRB
from .tomography import StateTomography, ProcessTomography
from .tomography import (
StateTomography,
ProcessTomography,
MitigatedStateTomography,
MitigatedProcessTomography,
)
from .quantum_volume import QuantumVolume

# Experiment Sub-modules
Expand Down
7 changes: 6 additions & 1 deletion qiskit_experiments/library/tomography/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

StateTomography
ProcessTomography
MitigatedStateTomography
MitigatedProcessTomography


Analysis
Expand All @@ -37,7 +39,7 @@

StateTomographyAnalysis
ProcessTomographyAnalysis

MitigatedTomographyAnalysis

Tomography Fitters
==================
Expand Down Expand Up @@ -90,6 +92,9 @@
# Experiment Classes
from .qst_experiment import StateTomography, StateTomographyAnalysis
from .qpt_experiment import ProcessTomography, ProcessTomographyAnalysis
from .mit_qst_experiment import MitigatedStateTomography
from .mit_qpt_experiment import MitigatedProcessTomography
from .mit_tomography_analysis import MitigatedTomographyAnalysis

# Basis Classes
from . import basis
Expand Down
111 changes: 111 additions & 0 deletions qiskit_experiments/library/tomography/mit_qpt_experiment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 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.
"""
Quantum Process Tomography experiment
"""

from typing import Union, Optional, Iterable, List, Tuple, Sequence
from qiskit.providers.backend import Backend
from qiskit.circuit import QuantumCircuit, Instruction
from qiskit.quantum_info.operators.base_operator import BaseOperator
from qiskit_experiments.framework import BatchExperiment, BaseAnalysis
from qiskit_experiments.library.characterization.local_readout_error import LocalReadoutError
from .qpt_experiment import ProcessTomography
from .mit_tomography_analysis import MitigatedTomographyAnalysis
from . import basis


class MitigatedProcessTomography(BatchExperiment):
"""Readout error mitigated quantum process tomography experiment.

# section: overview
Readout error mitigated Quantum process tomography is a batch
experiment consisting of a :class:`~.LocalReadoutError` characterization
experiments, followed by a :class:`~.ProcessTomography` experiment.

During analysis the assignment matrix local readout error model is
used to automatically construct a noisy Pauli measurement basis for
performing readout error mitigated process tomography fitting.

# section: note
Performing readout error mitigation full process tomography on an
`N`-qubit circuit requires running 2 readout error characterization
circuits and :math:`4^N 3^N` measurement circuits using the Pauli
preparation and measurement bases.

# section: analysis_ref
:py:class:`MitigatedTomographyAnalysis`

# section: see_also
qiskit_experiments.library.ProcessTomography
qiskit_experiments.library.LocalReadoutError

"""

def __init__(
self,
circuit: Union[QuantumCircuit, Instruction, BaseOperator],
backend: Optional[Backend] = None,
physical_qubits: Optional[Sequence[int]] = None,
measurement_indices: Optional[Sequence[int]] = None,
preparation_indices: Optional[Sequence[int]] = None,
basis_indices: Optional[Iterable[Tuple[List[int], List[int]]]] = None,
analysis: Union[BaseAnalysis, None, str] = "default",
):
"""Initialize a quantum process tomography experiment.

Args:
circuit: the quantum process circuit. If not a quantum circuit
it must be a class that can be appended to a quantum circuit.
backend: The backend to run the experiment on.
physical_qubits: Optional, the physical qubits for the initial state circuit.
If None this will be qubits [0, N) for an N-qubit circuit.
measurement_indices: Optional, the `physical_qubits` indices to be measured.
If None all circuit physical qubits will be measured.
preparation_indices: Optional, the `physical_qubits` indices to be prepared.
If None all circuit physical qubits will be prepared.
basis_indices: Optional, a list of basis indices for generating partial
tomography measurement data. Each item should be given as a pair of
lists of preparation and measurement basis configurations
``([p[0], p[1], ..], m[0], m[1], ...])``, where ``p[i]`` is the
preparation basis index, and ``m[i]`` is the measurement basis index
for qubit-i. If not specified full tomography for all indices of the
preparation and measurement bases will be performed.
analysis: Optional, a custom tomography analysis instance to use.
If ``"default"`` :class:`~.ProcessTomographyAnalysis` will be
used. If None no analysis instance will be set.
"""
tomo_exp = ProcessTomography(
circuit,
backend=backend,
physical_qubits=physical_qubits,
measurement_basis=basis.PauliMeasurementBasis(),
measurement_indices=measurement_indices,
preparation_basis=basis.PauliPreparationBasis(),
preparation_indices=preparation_indices,
basis_indices=basis_indices,
analysis=analysis,
)

roerror_exp = LocalReadoutError(
tomo_exp.physical_qubits,
backend=backend,
)

if analysis is None:
mit_analysis = (None,)
else:
mit_analysis = MitigatedTomographyAnalysis(roerror_exp.analysis, tomo_exp.analysis)

super().__init__(
[roerror_exp, tomo_exp], backend=backend, flatten_results=True, analysis=mit_analysis
)
104 changes: 104 additions & 0 deletions qiskit_experiments/library/tomography/mit_qst_experiment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 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.
"""
Quantum State Tomography experiment
"""

from typing import Union, Optional, List, Sequence
from qiskit.providers.backend import Backend
from qiskit.circuit import QuantumCircuit, Instruction
from qiskit.quantum_info.operators.base_operator import BaseOperator
from qiskit_experiments.framework import BatchExperiment, BaseAnalysis
from qiskit_experiments.library.characterization.local_readout_error import LocalReadoutError
from .qst_experiment import StateTomography
from .mit_tomography_analysis import MitigatedTomographyAnalysis
from . import basis


class MitigatedStateTomography(BatchExperiment):
"""Readout error mitigated quantum state tomography experiment.

# section: overview
Readout error mitigated quantum state tomography is a batch
experiment consisting of a :class:`~.LocalReadoutError` characterization
experiments, followed by a :class:`~.StateTomography` experiment.

During analysis the assignment matrix local readout error model is
used to automatically construct a noisy Pauli measurement basis for
performing readout error mitigated state tomography fitting.

# section: note
Performing readout error mitigation full state tomography on an
`N`-qubit circuit requires running 2 readout error characterization
circuits and :math:`3^N` measurement circuits using the Pauli
measurement basis.

# section: analysis_ref
:py:class:`MitigatedTomographyAnalysis`

# section: see_also
qiskit_experiments.library.StateTomography
qiskit_experiments.library.LocalReadoutError

"""

def __init__(
self,
circuit: Union[QuantumCircuit, Instruction, BaseOperator],
backend: Optional[Backend] = None,
physical_qubits: Optional[Sequence[int]] = None,
measurement_indices: Optional[Sequence[int]] = None,
basis_indices: Optional[Sequence[List[int]]] = None,
analysis: Union[BaseAnalysis, None, str] = "default",
):
"""Initialize a quantum process tomography experiment.

Args:
circuit: the quantum process circuit. If not a quantum circuit
it must be a class that can be appended to a quantum circuit.
backend: The backend to run the experiment on.
physical_qubits: Optional, the physical qubits for the initial state circuit.
If None this will be qubits [0, N) for an N-qubit circuit.
measurement_indices: Optional, the `physical_qubits` indices to be measured.
If None all circuit physical qubits will be measured.
basis_indices: Optional, a list of basis indices for generating partial
tomography measurement data. Each item should be given as a list of
measurement basis configurations ``[m[0], m[1], ...]`` where ``m[i]``
is the measurement basis index for qubit-i. If not specified full
tomography for all indices of the measurement basis will be performed.
analysis: Optional, a custom tomography analysis instance to use.
If ``"default"`` :class:`~.ProcessTomographyAnalysis` will be
used. If None no analysis instance will be set.
"""
tomo_exp = StateTomography(
circuit,
backend=backend,
physical_qubits=physical_qubits,
measurement_basis=basis.PauliMeasurementBasis(),
measurement_indices=measurement_indices,
basis_indices=basis_indices,
analysis=analysis,
)

roerror_exp = LocalReadoutError(
tomo_exp.physical_qubits,
backend=backend,
)

if analysis is None:
mit_analysis = (None,)
else:
mit_analysis = MitigatedTomographyAnalysis(roerror_exp.analysis, tomo_exp.analysis)

super().__init__(
[roerror_exp, tomo_exp], backend=backend, flatten_results=True, analysis=mit_analysis
)
127 changes: 127 additions & 0 deletions qiskit_experiments/library/tomography/mit_tomography_analysis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 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.
"""
Readout error mitigated tomography analysis
"""

from qiskit_experiments.framework import CompositeAnalysis
from qiskit_experiments.library.characterization import LocalReadoutErrorAnalysis
from .tomography_analysis import TomographyAnalysis
from .basis.pauli_basis import PauliMeasurementBasis


class MitigatedTomographyAnalysis(CompositeAnalysis):
"""Analysis for readout error mitigated tomography experiments.

Analysis is performed as a :class:`.CompositeAnalysis` consisting
of :class:`.LocalReadoutErrorAnalysis` to determine the local
assigment matrices describing single qubit Z-basis readout errors,
and then these matrices are used to automatically construct a noisy
:class:`~.PauliMeasurementBasis` for use during tomographic
fitting with the tomography analysis.
"""

def __init__(self, roerror_analysis="default", tomography_analysis="default"):
"""Initialize mitigated tomography analysis"""
if roerror_analysis == "default":
roerror_analysis = LocalReadoutErrorAnalysis()
if tomography_analysis == "default":
tomography_analysis = TomographyAnalysis()
super().__init__([roerror_analysis, tomography_analysis], flatten_results=True)

@classmethod
def _default_options(cls):
"""Default analysis options

Analysis Options:
fitter (str or Callable): The fitter function to use for reconstruction.
This can be a string to select one of the built-in fitters, or a callable to
supply a custom fitter function. See the `Fitter Functions` section for
additional information.
fitter_options (dict): Any addition kwarg options to be supplied to the fitter
function. For documentation of available kwargs refer to the fitter function
documentation.
rescale_positive (bool): If True rescale the state returned by the fitter
to be positive-semidefinite. See the `PSD Rescaling` section for
additional information (Default: True).
rescale_trace (bool): If True rescale the state returned by the fitter
have either trace 1 for :class:`~qiskit.quantum_info.DensityMatrix`,
or trace dim for :class:`~qiskit.quantum_info.Choi` matrices (Default: True).
measurement_qubits (Sequence[int]): Optional, the physical qubits with tomographic
measurements. If not specified will be set to ``[0, ..., N-1]`` for N-qubit
tomographic measurements.
preparation_qubits (Sequence[int]): Optional, the physical qubits with tomographic
preparations. If not specified will be set to ``[0, ..., N-1]`` for N-qubit
tomographic preparations.
unmitigated_fit (bool): If True also run tomography fit without readout error
mitigation and include both mitigated and unmitigated analysis results. If
False only compute mitigated results (Default: False)
target (Any): Optional, target object for fidelity comparison of the fit
(Default: None).
"""
# Override options to be tomography options minus bases
options = super()._default_options()
options.fitter = "linear_inversion"
options.fitter_options = {}
options.rescale_positive = True
options.rescale_trace = True
options.measurement_qubits = None
options.preparation_qubits = None
options.unmitigated_fit = False
options.target = None
return options

def set_options(self, **fields):
# filter fields
self_fields = {key: val for key, val in fields.items() if hasattr(self.options, key)}
super().set_options(**self_fields)
tomo_fields = {
key: val for key, val in fields.items() if hasattr(self._analyses[1].options, key)
}
self._analyses[1].set_options(**tomo_fields)

def _run_analysis(self, experiment_data):
# Return list of experiment data containers for each component experiment
# containing the marginalized data from the composite experiment
roerror_analysis, tomo_analysis = self._analyses
roerror_data, tomo_data = self._component_experiment_data(experiment_data)

# Run readout error analysis
roerror_analysis.run(roerror_data, replace_results=True).block_for_results()

# Construct noisy measurement basis
mitigator = roerror_data.analysis_results(0).value

# Construct noisy measurement basis
measurement_basis = PauliMeasurementBasis(mitigator=mitigator)
tomo_analysis.set_options(measurement_basis=measurement_basis)

# Run mitigated tomography analysis
tomo_analysis.run(tomo_data, replace_results=True).block_for_results()
for res in tomo_data.analysis_results(block=False):
res.extra["mitigated"] = True

# Combine results so that tomography results are ordered first
combined_data = [tomo_data, roerror_data]

# Run unmitigated tomography analysis
if self.options.unmitigated_fit:
tomo_analysis.set_options(measurement_basis=PauliMeasurementBasis())
nomit_data = tomo_analysis.run(tomo_data, replace_results=False).block_for_results()
for res in nomit_data.analysis_results(block=False):
res.extra["mitigated"] = False
combined_data.append(nomit_data)

if self._flatten_results:
return self._combine_results(combined_data)

return [], []
Loading