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

Fixing and documenting how the Estimator calculates stds #12670

Merged
merged 17 commits into from
Jul 18, 2024
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
26 changes: 22 additions & 4 deletions qiskit/primitives/backend_estimator_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class _PreprocessedData:


class BackendEstimatorV2(BaseEstimatorV2):
"""Evaluates expectation values for provided quantum circuit and observable combinations
r"""Evaluates expectation values for provided quantum circuit and observable combinations.

The :class:`~.BackendEstimatorV2` class is a generic implementation of the
:class:`~.BaseEstimatorV2` interface that is used to wrap a :class:`~.BackendV2`
Expand All @@ -87,7 +87,19 @@ class BackendEstimatorV2(BaseEstimatorV2):
precludes doing any provider- or backend-specific optimizations.

This class does not perform any measurement or gate mitigation, and, presently, is only
compatible with Pauli-based observables.
compatible with Pauli-based observables. More formally, given an observable of the type
:math:`O=\sum_{i=1}^Na_iP_i`, where :math:`a_i` is a complex number and :math:`P_i` is a
Pauli operator, the estimator calculates the expectation :math:`\mathbb{E}(P_i)` of each
:math:`P_i` and finally calculates the expectation value of :math:`O` as
:math:`\mathbb{E}(O)=\sum_{i=1}^Na_i\mathbb{E}(P_i)`. The reported ``std`` is calculated
as

.. math::

\frac{\sum_{i=1}^{n}|a_i|\sqrt{\textrm{Var}\big(P_i\big)}}{\sqrt{N}}\:,
Copy link
Contributor

Choose a reason for hiding this comment

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

what is \: ? I've never used that

Suggested change
\frac{\sum_{i=1}^{n}|a_i|\sqrt{\textrm{Var}\big(P_i\big)}}{\sqrt{N}}\:,
\frac{\sum_{i=1}^{n}|a_i|\sqrt{\textrm{Var}\big(P_i\big)}}{\sqrt{N}},

Copy link
Contributor

Choose a reason for hiding this comment

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

what's the link to that paper which suggests this? it's not intuitive to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Eq. 5 of https://arxiv.org/abs/1908.06942. I added a reference to it in the docstring

Copy link
Contributor Author

Choose a reason for hiding this comment

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

\: leaves a blank space. I normally use it when I have a comma or a break at the end of a full-line equation


where :math:`\textrm{Var}(P_i)` is the variance of :math:`P_i`, :math:`N=O(\epsilon^{-2})` is
the number of shots, and :math:`\epsilon` is the target precision [1].

Each tuple of ``(circuit, observables, <optional> parameter values, <optional> precision)``,
called an estimator primitive unified bloc (PUB), produces its own array-based result. The
Expand All @@ -104,6 +116,12 @@ class BackendEstimatorV2(BaseEstimatorV2):

* ``seed_simulator``: The seed to use in the simulator. If None, a random seed will be used.
Default: None.

**Reference:**

[1] O. Crawford, B. van Straaten, D. Wang, T. Parks, E. Campbell, St. Brierley,
Efficient quantum measurement of Pauli operators in the presence of finite sampling error.
`Quantum 5, 385 <https://doi.org/10.22331/q-2021-01-20-385>`_
"""

def __init__(
Expand Down Expand Up @@ -254,8 +272,8 @@ def _postprocess_pub(
for pauli, coeff in bc_obs[index].items():
expval, variance = expval_map[param_index, pauli]
evs[index] += expval * coeff
variances[index] += variance * coeff**2
stds = np.sqrt(variances / shots)
variances[index] += np.abs(coeff) * variance**0.5
stds = variances / np.sqrt(shots)
data_bin = DataBin(evs=evs, stds=stds, shape=evs.shape)
return PubResult(data_bin, metadata={"target_precision": pub.precision})

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
fixes:
- |
Changes the way in which the :class:`.BackendEstimatorV2` class calculates the ``std`` to ensure that
it matches the correct formula.
Loading