-
Notifications
You must be signed in to change notification settings - Fork 127
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
Adopt qiskit.result.mitigation
into qiskit_experiments.data_processing
#1484
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,25 +47,16 @@ experiments to generate the corresponding mitigators. | |
import numpy as np | ||
import matplotlib.pyplot as plt | ||
from qiskit import QuantumCircuit | ||
from qiskit.quantum_info import Operator | ||
from qiskit.visualization import plot_distribution | ||
from qiskit_experiments.data_processing import LocalReadoutMitigator | ||
from qiskit_experiments.library import LocalReadoutError, CorrelatedReadoutError | ||
|
||
from qiskit_aer import AerSimulator | ||
from qiskit_ibm_runtime.fake_provider import FakePerth | ||
|
||
from qiskit.result.mitigation.utils import ( | ||
expval_with_stddev, | ||
str2diag, | ||
counts_probability_vector | ||
) | ||
|
||
backend = AerSimulator.from_backend(FakePerth()) | ||
|
||
.. jupyter-execute:: | ||
|
||
shots = 1024 | ||
qubits = [0,1,2,3] | ||
num_qubits = len(qubits) | ||
|
||
Standard mitigation experiment | ||
------------------------------ | ||
|
@@ -76,13 +67,14 @@ circuits, one for all “0” and one for all “1” results. | |
|
||
.. jupyter-execute:: | ||
|
||
shots = 1024 | ||
qubits = [0,1,2,3] | ||
num_qubits = len(qubits) | ||
|
||
exp = LocalReadoutError(qubits) | ||
for c in exp.circuits(): | ||
print(c) | ||
|
||
|
||
.. jupyter-execute:: | ||
|
||
exp.analysis.set_options(plot=True) | ||
result = exp.run(backend) | ||
mitigator = result.analysis_results("Local Readout Mitigator").value | ||
|
@@ -102,9 +94,9 @@ The individual mitigation matrices can be read off the mitigator. | |
|
||
.. jupyter-execute:: | ||
|
||
for m in mitigator._mitigation_mats: | ||
print(m) | ||
print() | ||
for qubit in mitigator.qubits: | ||
print(f"Qubit: {qubit}") | ||
print(mitigator.mitigation_matrix(qubits=qubit)) | ||
|
||
|
||
Mitigation example | ||
|
@@ -118,13 +110,9 @@ Mitigation example | |
qc.cx(i - 1, i) | ||
qc.measure_all() | ||
|
||
.. jupyter-execute:: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also merged adjacent |
||
|
||
counts = backend.run(qc, shots=shots, seed_simulator=42, method="density_matrix").result().get_counts() | ||
unmitigated_probs = {label: count / shots for label, count in counts.items()} | ||
|
||
.. jupyter-execute:: | ||
|
||
mitigated_quasi_probs = mitigator.quasi_probabilities(counts) | ||
mitigated_stddev = mitigated_quasi_probs._stddev_upper_bound | ||
mitigated_probs = (mitigated_quasi_probs.nearest_probability_distribution().binary_probabilities()) | ||
|
@@ -144,15 +132,20 @@ Expectation value | |
.. jupyter-execute:: | ||
|
||
diagonal_labels = ["ZZZZ", "ZIZI", "IZII", "1ZZ0"] | ||
ideal_expectation = [] | ||
diagonals = [str2diag(d) for d in diagonal_labels] | ||
diagonals = [ | ||
np.diag(np.real(Operator.from_label(d).to_matrix())) | ||
for d in diagonal_labels | ||
] | ||
|
||
# Create a mitigator with no mitigation so that we can use its | ||
# expectation_values method to generate an unmitigated expectation value to | ||
# compare to the mitigated one. | ||
identity_mitigator = LocalReadoutMitigator([np.eye(2) for _ in range(4)]) | ||
|
||
qubit_index = {i: i for i in range(num_qubits)} | ||
unmitigated_probs_vector, _ = counts_probability_vector(unmitigated_probs, qubit_index=qubit_index) | ||
unmitigated_expectation = [expval_with_stddev(d, unmitigated_probs_vector, shots) for d in diagonals] | ||
unmitigated_expectation = [identity_mitigator.expectation_value(counts, d) for d in diagonals] | ||
mitigated_expectation = [mitigator.expectation_value(counts, d) for d in diagonals] | ||
|
||
.. jupyter-execute:: | ||
|
||
mitigated_expectation_values, mitigated_stddev = zip(*mitigated_expectation) | ||
unmitigated_expectation_values, unmitigated_stddev = zip(*unmitigated_expectation) | ||
legend = ['Mitigated Expectation', 'Unmitigated Expectation'] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# This code is part of Qiskit. | ||
# | ||
# (C) Copyright IBM 2017, 2021. | ||
# | ||
# 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 mitigation.""" | ||
from .base_readout_mitigator import BaseReadoutMitigator | ||
from .correlated_readout_mitigator import CorrelatedReadoutMitigator | ||
from .local_readout_mitigator import LocalReadoutMitigator | ||
from .utils import ( | ||
counts_probability_vector, | ||
expval_with_stddev, | ||
stddev, | ||
str2diag, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# This code is part of Qiskit. | ||
# | ||
# (C) Copyright IBM 2021 | ||
# | ||
# 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. | ||
""" | ||
Base class for readout error mitigation. | ||
""" | ||
|
||
from abc import ABC, abstractmethod | ||
from typing import Optional, List, Iterable, Tuple, Union, Callable | ||
|
||
import numpy as np | ||
|
||
from qiskit.result.counts import Counts | ||
from qiskit.result.distributions.quasi import QuasiDistribution | ||
|
||
|
||
class BaseReadoutMitigator(ABC): | ||
"""Base readout error mitigator class.""" | ||
|
||
@abstractmethod | ||
def quasi_probabilities( | ||
self, | ||
data: Counts, | ||
qubits: Iterable[int] = None, | ||
clbits: Optional[List[int]] = None, | ||
shots: Optional[int] = None, | ||
) -> QuasiDistribution: | ||
"""Convert counts to a dictionary of quasi-probabilities | ||
|
||
Args: | ||
data: Counts to be mitigated. | ||
qubits: the physical qubits measured to obtain the counts clbits. | ||
If None these are assumed to be qubits [0, ..., N-1] | ||
for N-bit counts. | ||
clbits: Optional, marginalize counts to just these bits. | ||
shots: Optional, the total number of shots, if None shots will | ||
be calculated as the sum of all counts. | ||
|
||
Returns: | ||
QuasiDistribution: A dictionary containing pairs of [output, mean] where "output" | ||
is the key in the dictionaries, | ||
which is the length-N bitstring of a measured standard basis state, | ||
and "mean" is the mean of non-zero quasi-probability estimates. | ||
""" | ||
|
||
@abstractmethod | ||
def expectation_value( | ||
self, | ||
data: Counts, | ||
diagonal: Union[Callable, dict, str, np.ndarray], | ||
qubits: Iterable[int] = None, | ||
clbits: Optional[List[int]] = None, | ||
shots: Optional[int] = None, | ||
) -> Tuple[float, float]: | ||
"""Calculate the expectation value of a diagonal Hermitian operator. | ||
|
||
Args: | ||
data: Counts object to be mitigated. | ||
diagonal: the diagonal operator. This may either be specified | ||
as a string containing I,Z,0,1 characters, or as a | ||
real valued 1D array_like object supplying the full diagonal, | ||
or as a dictionary, or as Callable. | ||
qubits: the physical qubits measured to obtain the counts clbits. | ||
If None these are assumed to be qubits [0, ..., N-1] | ||
for N-bit counts. | ||
clbits: Optional, marginalize counts to just these bits. | ||
shots: Optional, the total number of shots, if None shots will | ||
be calculated as the sum of all counts. | ||
|
||
Returns: | ||
The mean and an upper bound of the standard deviation of operator | ||
expectation value calculated from the current counts. | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Besides changing the import location of the mitigators, I made some small changes to this manual to stop using private functions and methods.