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

[WIP] Add M3 measurement mitigation #6748

Closed
wants to merge 51 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
bbcfb89
[WIP] Add M3 mitigation
nonhermitian Jul 14, 2021
ca1c3c8
remove cpp code
nonhermitian Jul 14, 2021
8fc7a04
Merge branch 'main' into add_m3
nonhermitian Jul 14, 2021
b16357c
fix need for numpy in setup
nonhermitian Jul 14, 2021
746dce8
Merge branch 'add_m3' of https://github.com/nonhermitian/qiskit-terra…
nonhermitian Jul 14, 2021
bb3bb20
get my version right
nonhermitian Jul 14, 2021
29ab466
move classes over to Qiskit distributions
nonhermitian Jul 14, 2021
12a85cb
Add testing cython modules
nonhermitian Jul 14, 2021
39f9aca
Add NumPy to pyproject per Matthews hint
nonhermitian Jul 14, 2021
23753b5
Add orjson to the dependencies
nonhermitian Jul 14, 2021
5a891e8
black
nonhermitian Jul 14, 2021
a1fb24a
cleaning some
nonhermitian Jul 14, 2021
b779b37
add column tests
nonhermitian Jul 14, 2021
1128da1
fix circular
nonhermitian Jul 14, 2021
7d61a0e
add converts test
nonhermitian Jul 14, 2021
eac755b
Add full test
nonhermitian Jul 14, 2021
b471a72
black
nonhermitian Jul 14, 2021
5bc5928
remove cpp files
nonhermitian Jul 14, 2021
f52cce4
fix stupid
nonhermitian Jul 14, 2021
15c06c2
fix more stupid
nonhermitian Jul 14, 2021
f4e3830
add missing imports
nonhermitian Jul 14, 2021
375b3ed
remove code that breaks unittests
nonhermitian Jul 14, 2021
93578f5
black again
nonhermitian Jul 14, 2021
75e9577
remove extraneious tests
nonhermitian Jul 15, 2021
3951b7e
black for the millionth time
nonhermitian Jul 15, 2021
1ee02f9
fix probabilities
nonhermitian Jul 15, 2021
a615113
black
nonhermitian Jul 15, 2021
da0846d
more tests and lint fix
nonhermitian Jul 15, 2021
7e66087
fix methods tests
nonhermitian Jul 15, 2021
c620386
fix code
nonhermitian Jul 15, 2021
1af37e0
explicitly set callback type
nonhermitian Jul 15, 2021
351b2c2
black again
nonhermitian Jul 15, 2021
7304bcb
add ignores
nonhermitian Jul 15, 2021
4736a13
more tests
nonhermitian Jul 15, 2021
49d9008
fix issues
nonhermitian Jul 15, 2021
924470e
fixes
nonhermitian Jul 15, 2021
c095616
more updates
nonhermitian Jul 15, 2021
f612252
fix left over sqrt
nonhermitian Jul 15, 2021
7c079fa
fixes
nonhermitian Jul 15, 2021
514023e
change fake backend in case Aer not in CI
nonhermitian Jul 15, 2021
b6880af
Merge branch 'main' into add_m3
nonhermitian Jul 15, 2021
d51b4a7
fix test
nonhermitian Jul 15, 2021
0095741
fix test
nonhermitian Jul 15, 2021
4328dc7
remove unused exceptions
nonhermitian Jul 16, 2021
dcb626c
Merge remote-tracking branch 'origin/main' into nonhermitian-add_m3
mtreinish Jul 22, 2021
a4fb807
Switch from orjson to stdlib json and fix json tests
mtreinish Jul 22, 2021
2ea2287
remove unused import
nonhermitian Jul 30, 2021
c7c48a2
post
nonhermitian Aug 3, 2021
2831105
Add mitigation section to docs
nonhermitian Aug 3, 2021
e3a86c9
added notes
nonhermitian Aug 3, 2021
7519315
Add module docs
nonhermitian Aug 3, 2021
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
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,13 @@ src/qasm-simulator-cpp/test/qubit_vector_tests
# Cython pass
qiskit/transpiler/passes/**/cython/**/*.cpp
qiskit/quantum_info/states/cython/*.cpp
qiskit/mitigation/mthree/*.cpp
qiskit/mitigation/mthree/test/*.cpp
qiskit/result/distributions/*.cpp

docs/stubs/*

# Notebook testing images
test/ipynb/mpl/*.png
test/ipynb/mpl/*.zip
test/ipynb/mpl/result_test.json
test/ipynb/mpl/circuit/*.png
test/ipynb/mpl/circuit/*.zip
test/ipynb/mpl/circuit/result_test.json
Expand Down
6 changes: 6 additions & 0 deletions docs/apidocs/mitigation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. _qiskit-mitigtion:

.. automodule:: qiskit.mitigation
:no-members:
:no-inherited-members:
:no-special-members:
1 change: 1 addition & 0 deletions docs/apidocs/terra.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ Qiskit Terra API Reference
visualization
opflow
algorithms
mitigation
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[build-system]
requires = ["Cython>=0.27.1", "setuptools", "wheel"]
requires = ["Cython>=0.27.1", "numpy>=1.17", "setuptools", "wheel"]

[tool.black]
line-length = 100
Expand Down
33 changes: 33 additions & 0 deletions qiskit/mitigation/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# 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.

"""Error mitigation routines

===========================================
Error mitigation (:mod:`qiskit.mitigation`)
===========================================

.. versionadded:: 0.19.0

.. currentmodule:: qiskit.mitigation

Measurement mitigation
======================

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

M3Mitigation

"""

from .mthree import M3Mitigation
16 changes: 16 additions & 0 deletions qiskit/mitigation/mthree/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# 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.

"""Matrix-free measurement mitigation.
"""

from .mitigation import M3Mitigation
30 changes: 30 additions & 0 deletions qiskit/mitigation/mthree/compute.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# 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.

cdef unsigned int within_distance(unsigned int row,
unsigned int col,
const unsigned char * bitstrings,
unsigned int num_bits,
unsigned int distance) nogil

cdef double compute_element(unsigned int row,
unsigned int col,
const unsigned char * bitstrings,
const double * cals,
unsigned int num_bits) nogil

cdef void compute_col_norms(double * col_norms,
const unsigned char * bitstrings,
const double * cals,
unsigned int num_bits,
unsigned int num_elems,
unsigned int distance) nogil
137 changes: 137 additions & 0 deletions qiskit/mitigation/mthree/compute.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# 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.
cimport cython
from cython.parallel cimport prange

@cython.boundscheck(False)
@cython.cdivision(True)
cdef inline unsigned int within_distance(unsigned int row,
unsigned int col,
const unsigned char * bitstrings,
unsigned int num_bits,
unsigned int distance) nogil:
"""Computes the Hamming distance between two bitstrings.

Parameters:
row (unsigned int): The row index.
col (unsigned int): The col index.
bitstrings (unsigned char *): Pointer to array of all bitstrings.
num_bits (unsigned int): The number of bits in a bitstring.
distance (unsigned int): The distance to calculate out to.

Returns:
unsigned int: Are the bitstrings within given distance.
"""

cdef size_t kk
cdef unsigned int temp_dist = 0
cdef unsigned int row_start = row*num_bits
cdef unsigned int col_start = col*num_bits

for kk in range(num_bits):
temp_dist += bitstrings[row_start+kk] != bitstrings[col_start+kk]
return temp_dist <= distance

@cython.boundscheck(False)
@cython.cdivision(True)
cdef inline double compute_element(unsigned int row,
unsigned int col,
const unsigned char * bitstrings,
const double * cals,
unsigned int num_bits) nogil:
"""Computes the matrix element specified by the input
bit strings from the supplied tensored cals data.

Parameters:
row_arr (unsigned char *): Basis element giving row index.
col_arr (unsigned char *): Basis element giving col index.
cals (const double *): Tensored calibration data.
num_qubits (unsigned int): Number of qubits in arrays

Returns:
double: Matrix element value.
"""
cdef double res = 1
cdef size_t kk
cdef unsigned int offset
cdef unsigned int row_start = num_bits*row
cdef unsigned int col_start = num_bits*col

for kk in range(num_bits):
offset = 2*bitstrings[row_start+kk]+bitstrings[col_start+kk]
res *= cals[4*kk+offset]
return res

@cython.boundscheck(False)
@cython.cdivision(True)
cdef void compute_col_norms(double * col_norms,
const unsigned char * bitstrings,
const double * cals,
unsigned int num_bits,
unsigned int num_elems,
unsigned int distance) nogil:
"""Compute the matrix column norms for each bitstring.

Parameters:
col_norms (double *): Pointer to double array in which to poulate norms.
bitstrings (unsigned char *): Pointer to array of all bitstrings.
num_bits (unsigned int): The number of bits in a bitstring.
num_elems (unsigned int): The number of bitstring elements.
distance (unsigned int): The distance to calculate out to.
"""
cdef size_t col, row
cdef double col_norm
cdef unsigned int MAX_DIST = 0

if distance == num_bits:
MAX_DIST = 1
# Compute the column norm for each element
with nogil:
for col in prange(num_elems, schedule='static'):
col_norm = _inner_col_norm_loop(col,
bitstrings,
cals,
num_bits,
num_elems,
distance,
MAX_DIST)
col_norms[col] = col_norm


cdef double _inner_col_norm_loop(unsigned int col,
const unsigned char * bitstrings,
const double * cals,
unsigned int num_bits,
unsigned int num_elems,
unsigned int distance,
unsigned int MAX_DIST) nogil:
"""An inner-loop function for computing col_norms in parallel.

This is needed to get around an issue with how Cython tries to do
OMP reductions.

Parameters:
col (int): The column of interest.
col_norms (double *): Pointer to double array in which to poulate norms.
bitstrings (unsigned char *): Pointer to array of all bitstrings.
num_bits (unsigned int): The number of bits in a bitstring.
num_elems (unsigned int): The number of bitstring elements.
distance (unsigned int): The distance to calculate out to.
MAX_DIST (unsigned int): Are we doing max distance.
"""
cdef size_t row
cdef double col_norm = 0

for row in range(num_elems):
if MAX_DIST or within_distance(row, col, bitstrings, num_bits, distance):
col_norm += compute_element(row, col, bitstrings, cals, num_bits)
return col_norm
23 changes: 23 additions & 0 deletions qiskit/mitigation/mthree/converters.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 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.
# cython: c_string_type=unicode, c_string_encoding=UTF-8
from libcpp.map cimport map
from libcpp.string cimport string

cdef void counts_to_internal(map[string, double] * counts,
unsigned char * vec,
double * probs,
unsigned int num_bits,
double shots)

cdef void internal_to_probs(map[string, double] * counts,
double * probs)
68 changes: 68 additions & 0 deletions qiskit/mitigation/mthree/converters.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# 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.
# cython: c_string_type=unicode, c_string_encoding=UTF-8
cimport cython
from libcpp.map cimport map
from libcpp.string cimport string
from cython.operator cimport dereference, postincrement

@cython.boundscheck(False)
@cython.cdivision(True)
cdef void counts_to_internal(map[string, double] * counts_map,
unsigned char * vec,
double * probs,
unsigned int num_bits,
double shots):
"""Converts a Qiskit counts object (or Python dict) into an array
of bitstrings and probabilities.

Parameters:
counts (object): A Qiskit counts object or Python dict.
vec (unsigned char *): Pointer to array of bitstrings to populate.
probs (double *): Pointer to array of probabilities to populate.
num_bits (unsigned int): Number of bits in the bitstrings.
"""
cdef unsigned int idx, letter, start
cdef map[string, double].iterator end = counts_map.end()
cdef map[string, double].iterator it = counts_map.begin()
cdef string temp
idx = 0
while it != end:
start = num_bits*idx
probs[idx] = dereference(it).second / shots
temp = dereference(it).first
for letter in range(num_bits):
vec[start+letter] = <unsigned char>temp[letter]-48
idx += 1
postincrement(it)


@cython.boundscheck(False)
@cython.cdivision(True)
cdef void internal_to_probs(map[string, double] * counts_map,
double * probs):
"""Converts internal arrays back into a Python dict.

Parameters:
vec (unsigned char *): Pointer to array of bitstrings.
vec (dobule *): Pointer to array of probabilities.
num_elems (unsigned int): Number of elements.
num_bits (unsigned int): Number of bits in the bitstrings.
"""
cdef size_t idx = 0
cdef map[string, double].iterator end = counts_map.end()
cdef map[string, double].iterator it = counts_map.begin()

while it != end:
dereference(it).second = probs[idx]
idx += 1
postincrement(it)
Loading