Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions docs/apidocs/terra.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Qiskit Terra API Reference
transpiler_passes
transpiler_preset
utils
utils_mitigation
visualization
opflow
algorithms
6 changes: 6 additions & 0 deletions docs/apidocs/utils_mitigation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. _qiskit-utils-mitigation:

.. automodule:: qiskit.utils.mitigation
:no-members:
:no-inherited-members:
:no-special-members:
63 changes: 33 additions & 30 deletions qiskit/utils/measurement_error_mitigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,19 @@

import copy
from typing import List, Optional, Tuple, Dict, Callable

from qiskit import compiler
from qiskit.providers import BaseBackend
from qiskit.circuit import QuantumCircuit
from qiskit.qobj import QasmQobj
from qiskit.assembler.run_config import RunConfig
from ..exceptions import QiskitError, MissingOptionalLibraryError
from qiskit.exceptions import QiskitError, MissingOptionalLibraryError
from qiskit.utils.mitigation import (
complete_meas_cal,
tensored_meas_cal,
CompleteMeasFitter,
TensoredMeasFitter,
)

# pylint: disable=invalid-name

Expand Down Expand Up @@ -137,35 +144,44 @@ def build_measurement_error_mitigation_circuits(
QiskitError: when the fitter_cls is not recognizable.
MissingOptionalLibraryError: Qiskit-Ignis not installed
"""
try:
from qiskit.ignis.mitigation.measurement import (
complete_meas_cal,
tensored_meas_cal,
CompleteMeasFitter,
TensoredMeasFitter,
)
except ImportError as ex:
raise MissingOptionalLibraryError(
libname="qiskit-ignis",
name="build_measurement_error_mitigation_qobj",
pip_install="pip install qiskit-ignis",
) from ex

circlabel = "mcal"

if not qubit_list:
raise QiskitError("The measured qubit list can not be [].")

run = False
if fitter_cls == CompleteMeasFitter:
meas_calibs_circuits, state_labels = complete_meas_cal(
qubit_list=range(len(qubit_list)), circlabel=circlabel
)
run = True
elif fitter_cls == TensoredMeasFitter:
meas_calibs_circuits, state_labels = tensored_meas_cal(
mit_pattern=mit_pattern, circlabel=circlabel
)
else:
raise QiskitError(f"Unknown fitter {fitter_cls}")
run = True
if not run:
try:
from qiskit.ignis.mitigation.measurement import (
CompleteMeasFitter as CompleteMeasFitter_IG,
TensoredMeasFitter as TensoredMeasFitter_IG,
)
except ImportError as ex:
raise MissingOptionalLibraryError(
libname="qiskit-ignis",
name="build_measurement_error_mitigation_qobj",
pip_install="pip install qiskit-ignis",
) from ex
Comment thread
mtreinish marked this conversation as resolved.
Outdated
if fitter_cls == CompleteMeasFitter_IG:
meas_calibs_circuits, state_labels = complete_meas_cal(
qubit_list=range(len(qubit_list)), circlabel=circlabel
)
elif fitter_cls == TensoredMeasFitter_IG:
meas_calibs_circuits, state_labels = tensored_meas_cal(
mit_pattern=mit_pattern, circlabel=circlabel
)
Comment thread
kdk marked this conversation as resolved.
else:
raise QiskitError(f"Unknown fitter {fitter_cls}")

# the provided `qubit_list` would be used as the initial layout to
# assure the consistent qubit mapping used in the main circuits.
Expand Down Expand Up @@ -209,19 +225,6 @@ def build_measurement_error_mitigation_qobj(
QiskitError: when the fitter_cls is not recognizable.
MissingOptionalLibraryError: Qiskit-Ignis not installed
"""
try:
from qiskit.ignis.mitigation.measurement import (
complete_meas_cal,
tensored_meas_cal,
CompleteMeasFitter,
TensoredMeasFitter,
)
except ImportError as ex:
raise MissingOptionalLibraryError(
libname="qiskit-ignis",
name="build_measurement_error_mitigation_qobj",
pip_install="pip install qiskit-ignis",
) from ex

Comment on lines 212 to 225

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the same attempt to import from Ignis for this function (build_measurement_error_mitigation_qobj) as we did in the previous one (build_measurement_error_mitigation_circuits)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not strictly necessary because the calibration circuits are the same. Above where we handle the ignis path we're actually just passing the terra version of the classes here.

If ignis were going to continue active feature development I would have added handling for calling ignis here just in case the cal circuits diverged, but since everything is pretty much froze and this is just for compat while the api for mitigation in algorithms is being redone I think this is fine.

circlabel = "mcal"

Expand Down
54 changes: 54 additions & 0 deletions qiskit/utils/mitigation/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2019.
#
# 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.

# This code was originally copied from the qiskit-ignis repsoitory see:
# https://github.com/Qiskit/qiskit-ignis/blob/b91066c72171bcd55a70e6e8993b813ec763cf41/qiskit/ignis/mitigation/measurement/__init__.py
# it was migrated as qiskit-ignis is being deprecated

"""
=============================================================
Measurement Mitigation Utils (:mod:`qiskit.utils.mitigation`)
=============================================================

.. currentmodule:: qiskit.utils.mitigation

Measurement correction
======================

The measurement calibration is used to mitigate measurement errors.
The main idea is to prepare all :math:`2^n` basis input states and compute
the probability of measuring counts in the other basis states.
From these calibrations, it is possible to correct the average results
of another experiment of interest. These tools are intended for use solely
with the :class:`~qiskit.utils.QuantumInstance` class as part of
:mod:`qiskit.algorithms` and :mod:`qiskit.opflow`.

.. warning::

The user facing API stability of this module is not guaranteed except for
their use with the :class:`~qiskit.utils.QuantumInstance` (ie using the
:class:`~qiskit.utils.mitigation.CompleteMeasFitter` or
:class:`~qiskit.utils.mitigation.TensoredMeasFitter` class as values for the
``meas_error_mitigation_cls``). The rest of this module should be treated as
an internal private API that can not be relied upon.

.. autosummary::
:toctree: ../stubs/

CompleteMeasFitter
TensoredMeasFitter
"""

# Measurement correction functions
from .circuits import complete_meas_cal, tensored_meas_cal
from .filters import MeasurementFilter, TensoredFilter
from .fitters import CompleteMeasFitter, TensoredMeasFitter
Comment on lines +52 to +53

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that the MeasurementFilter and TensoredFilter classes are meant to be entirely private, and users (and other parts of Qiskit except the two fitters here) shouldn't be creating or instantiating them at all. For example, there's no generated autosummary pages for them. Is it worth renaming their module to _filters.py, and not importing them in this __init__.py to follow Python conventions of public/private access and make the access pattern clear to consumers of Terra who aren't reading the documentation?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's not a bad idea. I was trying to avoid the _module.py pattern mostly because in the dark before times (i.e. before I first started working on Qiskit) pretty much every module was _foo.py and the user api was defined as the re-exported classes from the __init__.py (without __all__). See https://github.com/Qiskit/qiskit-terra/tree/0.5.0/qiskit if you'd like to get a more concrete feel for what I'm describing. It's left a bad taste ever since so I just try to avoid it so people aren't tempted to revert to that "model". But here I think it makes sense I'll update this accordingly.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha, that's quite the structure. It feels like there's valid intent behind it (perhaps attempting to force a canonical import path?), but yeah, that's gone pretty overboard.

Loading