Skip to content

Commit

Permalink
Better expval docs and minor class fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
nonhermitian committed Sep 5, 2021
1 parent 81561f2 commit 7a998fe
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 32 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,4 @@ mthree/version.py

docs/stubs/*
*.json
docs/tutorials/
101 changes: 75 additions & 26 deletions docs/expvals.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,49 +6,98 @@ Obtaining expectation values

Given a quasi- or standard probability distribution, it is possible to compute the
expectation value of diagonal operators directly from the distributions (or collections)
of distributions:
of distributions. This can be done using string representation for standard diagonal
operators such as ``I``, ``Z``, ``0`` or ``1``, or via dictionaries for custom operators.


Let us first generate some quasi-distributions by mitigating 2- and 3-qubit GHZ circuits on
a noisy-simulator.

.. jupyter-execute::

import numpy as np
from qiskit import *
from qiskit.circuit.library import TwoLocal
from qiskit.test.mock.backends import FakeCasablanca
from qiskit.test.mock import FakeAthens
import mthree

# Measure YZ
qc_yz = QuantumCircuit(2)
qc_yz.sdg(1)
qc_yz.h(1)
backend = FakeAthens()

# Measure XX
qc_xx = QuantumCircuit(2)
qc_xx.h(0)
qc_xx.h(1)
ghz2 = QuantumCircuit(2)
ghz2.h(0)
ghz2.cx(0,1)
ghz2.measure_all()

qc = TwoLocal(2, rotation_blocks='ry', entanglement_blocks='cx')
circs = [qc.compose(qc_yz), qc, qc, qc.compose(qc_xx)]
trans_ghz2 = transpile(ghz2, backend)

params = np.array([1.22253725, 0.39053752, 0.21462153, 5.48308027,
2.06984514, 3.65227416, 4.01911194, 0.35749589])
ghz3 = QuantumCircuit(3)
ghz3.h(0)
ghz3.cx(0,1)
ghz3.cx(1,2)
ghz3.measure_all()

bound_circs = [circ.bind_parameters(params).measure_all(inplace=False) for circ in circs]
trans_ghz3 = transpile(ghz3, backend)

raw2 = backend.run(trans_ghz2, shots=4000).result().get_counts()
raw3 = backend.run(trans_ghz3, shots=4000).result().get_counts()

backend = FakeCasablanca()
mit = mthree.M3Mitigation(backend)
mit.cals_from_system([0,1])
mit.cals_from_system()

quasi2 = mit.apply_correction(raw2, [0,1], return_mitigation_overhead=True)
quasi3 = mit.apply_correction(raw3, [0,1,2], return_mitigation_overhead=True)


Now let us compute the expectaion values of these distributions for the default
case of ``Z`` operators on each qubit:

.. jupyter-execute::

print('GHZ2:', quasi2.expval())
print('GHZ3:', quasi3.expval())


The values are close to one and zero, respectively. We can use strings to repeat the
above via:

.. jupyter-execute::

print('GHZ2:', quasi2.expval('ZZ'))
print('GHZ3:', quasi3.expval('ZZZ'))


trans_qc = transpile(bound_circs, backend)
raw_counts = backend.run(trans_qc, shots=4000).result().get_counts()
Replacing a ``Z`` measurement with an ``I`` on one of the qubits has the affect of changing the
sign for the :math:`|1>^{\otimes N}` component:

.. jupyter-execute::

print('GHZ2:', quasi2.expval('IZ'))
print('GHZ3:', quasi3.expval('ZIZ'))

We can also pass lists of strings:

.. jupyter-execute::

quasi3.expval_and_stddev(['ZZZ','ZIZ'])

Alternatively, users can specify their own custom diagonal operators using dictionaries. Here
we form the projectors on the all ones and zeros states:

.. jupyter-execute::

all_zeros_proj = {'000': 1}
all_ones_proj = {'111': 1}
quasi3.expval(all_zeros_proj)

Like strings, one can pass an array of dicts:

.. jupyter-execute::

quasis = mit.apply_correction(raw_counts, [0,1], return_mitigation_overhead=True)
quasi3.expval([all_zeros_proj, all_ones_proj])

quasis.expval()

By default, the expectation value is with respect to the standard Z-operators. However, it is
possible to pass other diagonal operators either as a string or a list. If given a list, the
number of elements must match the number of raw counts (in this example 4):
We can verify that the projectors return the correct values:

.. jupyter-execute::

quasis.expval(['ZZ', 'ZI', 'II', 'ZZ'])
p0s, p1s = quasi3.expval([all_zeros_proj, all_ones_proj])
np.allclose([p0s, p1s], [quasi3['000'], quasi3['111']])
30 changes: 24 additions & 6 deletions mthree/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,24 @@ def expval(self, exp_ops=''):
"""Compute expectation value from distribution.
Parameters:
exp_ops (stror dict ): String representation of diagonal qubit operators
used in computing the expectation value.
exp_ops (str or dict or list): String representation of diagonal
qubit operators
used in computing the expectation value.
Returns:
float: Expectation value.
Raises:
M3Error: Invalid type passed to exp_ops
"""
if isinstance(exp_ops, str):
return exp_val(self, exp_ops=exp_ops)
else:
elif isinstance(exp_ops, dict):
return exp_val(self, dict_ops=exp_ops)
elif isinstance(exp_ops, list):
return np.array([self.expval(item) for item in exp_ops], dtype=float)
else:
raise M3Error('Invalid type passed to exp_ops')

def stddev(self):
"""Compute standard deviation from distribution.
Expand Down Expand Up @@ -114,16 +122,26 @@ def expval(self, exp_ops=''):
"""Compute expectation value from distribution.
Parameters:
exp_ops (str or dict): String or dict representation of diagonal qubit operators
used in computing the expectation value.
exp_ops (str or dict or list): String or dict representation
of diagonal qubit operators
used in computing the expectation
value.
Returns:
float: Expectation value.
Raises:
M3Error: Invalid type passed to exp_ops.
"""
if isinstance(exp_ops, str):
return exp_val(self, exp_ops=exp_ops)
else:
elif isinstance(exp_ops, dict):
return exp_val(self, dict_ops=exp_ops)
elif isinstance(exp_ops, list):
return np.array([self.expval(item) for item in exp_ops], dtype=float)
else:
raise M3Error('Invalid type passed to exp_ops')


def stddev(self):
"""Compute standard deviation estimate from distribution.
Expand Down

0 comments on commit 7a998fe

Please sign in to comment.