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

Raise an error when we return sample() or counts() with observables that are not diagonal! #3199

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
dba242e
Update the Hermiticity check of `qml.Hermitian` to use `qml.math` (#2…
antalszava Aug 8, 2022
f0ba99e
important typo fix (#2901)
dwierichs Aug 8, 2022
d555420
test lightning (#2903)
antalszava Aug 8, 2022
2991a36
Update the readme and PennyLane Logo (#2912)
josh146 Aug 8, 2022
e25d514
Add warning to `qml.cond` docs about unsupported cases (#2883)
antalszava Aug 9, 2022
d2fb335
`qml.simplify` can reduce number of rotation parameters (#2905)
albi3ro Aug 9, 2022
49842b3
seed and flaky (#2917)
antalszava Aug 9, 2022
c2a7a9b
Fixes a bug where kUpCCGSD wasn't working with the parameter-shift ru…
isaacdevlugt Aug 9, 2022
a0e01c2
Add module documentation for `ops` (#2730)
albi3ro Aug 9, 2022
4b8869e
Fix check batching bug (#2900)
albi3ro Aug 10, 2022
4a7dfb6
raise error when sampling with other non-commuting observables
Jaybsoni Aug 10, 2022
400e640
lint
Jaybsoni Aug 10, 2022
fc12631
changelog
Jaybsoni Aug 10, 2022
1c12a1a
Apply suggestions from code review
Jaybsoni Aug 10, 2022
d6ae1c2
Update pennylane/_qubit_device.py
Jaybsoni Aug 10, 2022
5312eda
Apply suggestions from code review
Jaybsoni Aug 10, 2022
bae1778
Update development guide to explain `dev.stopping.condition` (#2925)
albi3ro Aug 10, 2022
3ba3dea
Merge branch 'v0.25.0-rc0' into sample_no_obs_bug
AlbertMitjans Aug 11, 2022
a8cd833
Fix test randomness for `ShotAdaptiveOptimizer` (#2929)
rmoyard Aug 11, 2022
04cf975
State finite shots warn (#2918)
antalszava Aug 11, 2022
4ce747b
Merge branch 'v0.25.0-rc0' into sample_no_obs_bug
Jaybsoni Aug 11, 2022
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
12 changes: 2 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
<p align="center">
<a href="https://pennylane.ai">
<img width=80% src="https://raw.githubusercontent.com/PennyLaneAI/pennylane/master/doc/_static/pennylane_thin.png">
</a>
</p>

<p align="center">
<!-- Tests (GitHub actions) -->
<a href="https://github.com/PennyLaneAI/pennylane/actions?query=workflow%3ATests">
Expand Down Expand Up @@ -147,10 +141,8 @@ PennyLane is the work of [many contributors](https://github.com/PennyLaneAI/penn

If you are doing research using PennyLane, please cite [our paper](https://arxiv.org/abs/1811.04968):

> Ville Bergholm, Josh Izaac, Maria Schuld, Christian Gogolin, M. Sohaib Alam, Shahnawaz Ahmed,
> Juan Miguel Arrazola, Carsten Blank, Alain Delgado, Soran Jahangiri, Keri McKiernan, Johannes Jakob Meyer,
> Zeyue Niu, Antal Száva, and Nathan Killoran.
> *PennyLane: Automatic differentiation of hybrid quantum-classical computations.* 2018. arXiv:1811.04968
> Ville Bergholm et al. *PennyLane: Automatic differentiation of hybrid quantum-classical
> computations.* 2018. arXiv:1811.04968

## License

Expand Down
Binary file removed doc/_static/building_blocks.png
Binary file not shown.
Binary file modified doc/_static/favicon.ico
Binary file not shown.
Binary file modified doc/_static/header-dark-mode.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/_static/header.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed doc/_static/intro.png
Binary file not shown.
Binary file modified doc/_static/jigsaw.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/_static/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed doc/_static/numpy.jpeg
Binary file not shown.
Binary file removed doc/_static/pennylane.png
Binary file not shown.
230 changes: 63 additions & 167 deletions doc/_static/pennylane.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed doc/_static/pennylane_big.png
Binary file not shown.
Binary file removed doc/_static/pennylane_thin.png
Binary file not shown.
Binary file modified doc/_static/pl_wordmark.png
100755 → 100644
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions doc/code/qml_ops_op_math.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
qml.ops.op_math
===============

.. automodule:: pennylane.ops.op_math
3 changes: 2 additions & 1 deletion doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@

# Xanadu theme options (see theme.conf for more information).
html_theme_options = {
"navbar_wordmark_path": "_static/pl_wordmark.png",
"navbar_logo_path": "_static/logo.png",
"navbar_wordmark_path": "_static/pennylane.svg",
# Specifying #19b37b is more correct but does not match the other PL websites.
"navbar_logo_colour": "#2d7c7f",
"navbar_home_link": "https://pennylane.ai",
Expand Down
15 changes: 11 additions & 4 deletions doc/development/adding_operators.rst
Original file line number Diff line number Diff line change
Expand Up @@ -213,16 +213,23 @@ FlipAndRotate(0.1, wires=['q3', 'q1'])
>>> op.adjoint()
FlipAndRotate(-0.1, wires=['q3', 'q1'])

The new gate can be used with PennyLane devices. PennyLane checks with the device
whether it supports operations using the operation name.
The new gate can be used with PennyLane devices. Device support for an operation can be checked via
``dev.stopping_condition(op)``. If ``True``, then the device supports the operation.

``DefaultQubit`` first checks if the operator has a matrix using the :attr:`~.Operator.has_matrix` property.
If the Operator doesn't have a matrix, the device then checks if the name of the Operator is explicitly specified in
:attr:`~DefaultQubit.operations` or :attr:`~DefaultQubit.observables`.

Other devices that do not inherit from ``DefaultQubit`` only check if the name is explicitly specified in the ``operations``
property.

- If the device registers support for an operation with the same name,
PennyLane leaves the gate implementation up to the device. The device
might have a hardcoded implementation, *or* it may refer to one of the
numerical representations of the operator (such as :meth:`.Operator.matrix`).

- If the device does not register support for an operation with the same
name, PennyLane will automatically decompose the gate using :meth:`.Operator.decomposition`.
- If the device does not support an operation, PennyLane will automatically
decompose the gate using :meth:`.Operator.decomposition`.

.. code-block:: python

Expand Down
20 changes: 18 additions & 2 deletions doc/development/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,27 @@ Device capabilities
You must further tell PennyLane about the operations that your device supports,
as well as potential further capabilities, by providing the following class attributes/properties:

* :attr:`.Device.operations`: a set of the supported PennyLane operations as strings, e.g.,
* :attr:`.Device.stopping_condition`: This :class:`~.BooleanFn` should return ``True`` for supported
operations and measurement processes, and ``False`` otherwise. Note that this function is called on
**both** ``Operator`` and ``MeasurementProcess`` classes. Though this function must accept both ``Operator``
and ``MeasurementProcess`` classes, it does not affect whether or not a ``MeasurementProcess`` is supported.

.. code-block:: python

operations = {"CNOT", "PauliX"}
@property
def stopping_condition(self):
def accepts_obj(obj):
return obj.name in {'CNOT', 'PauliX', 'PauliY', 'PauliZ'}
return qml.BooleanFn(accepts_obj)

If the device does *not* inherit from :class:`~.DefaultQubit`, then supported operations can be determined
by the :attr:`.Device.operations` property. This property is a list of string names for supported operations.
:class:`~.DefaultQubit` supports any operation with a matrix, even if it's name isn't specifically enumerated
in :attr:`.Device.operations`.

.. code-block:: python

operations = {"CNOT", "PauliX"}

See :doc:`/introduction/operations` for a full list of operations
supported by PennyLane.
Expand Down
9 changes: 4 additions & 5 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,9 @@ If you are doing research using PennyLane, please cite

.. rst-class:: admonition warning

Ville Bergholm, Josh Izaac, Maria Schuld, Christian Gogolin, M. Sohaib Alam, Shahnawaz Ahmed,
Juan Miguel Arrazola, Carsten Blank, Alain Delgado, Soran Jahangiri, Keri McKiernan, Johannes Jakob Meyer,
Zeyue Niu, Antal Száva, and Nathan Killoran.
*PennyLane: Automatic differentiation of hybrid quantum-classical computations.* 2018.
`arXiv:1811.04968 <https://arxiv.org/abs/1811.04968>`_
Ville Bergholm et al. *PennyLane: Automatic differentiation of hybrid
quantum-classical computations.* 2018. `arXiv:1811.04968
<https://arxiv.org/abs/1811.04968>`_

Support and contribution
------------------------
Expand Down Expand Up @@ -183,6 +181,7 @@ PennyLane is **free** and **open source**, released under the Apache License, Ve
code/qml_grouping
code/qml_kernels
code/qml_math
code/qml_ops_op_math
code/qml_qinfo
code/qml_numpy
code/qml_qaoa
Expand Down
30 changes: 25 additions & 5 deletions doc/introduction/operations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,45 @@ Operator functions
------------------

Various functions and transforms are available for manipulating operators,
and extracting information.
and extracting information. These can be broken down into two main categories:

Operator to Operator functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. autosummary::

~pennylane.adjoint
~pennylane.ctrl
~pennylane.cond
~pennylane.op_sum
~pennylane.prod
~pennylane.s_prod
~pennylane.generator

These operator functions act on operators to produce new operators.

>>> op = qml.prod(qml.PauliX(0), qml.PauliZ(1))
>>> op = qml.op_sum(qml.Hadamard(0), op)
>>> op = qml.s_prod(1.2, op)
1.2*(Hadamard(wires=[0]) + PauliX(wires=[0]) @ PauliZ(wires=[1]))

Operator to Other functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. autosummary::

~pennylane.matrix
~pennylane.eigvals
~pennylane.generator

All operator functions can be used on instantiated operators,
These operator functions act on operators and return other data types.
All operator functions can be used on instantiated operators.

>>> op = qml.RX(0.54, wires=0)
>>> qml.matrix(op)
[[0.9637709+0.j 0. -0.26673144j]
[0. -0.26673144j 0.9637709+0.j ]]

Operator functions can also be used in a functional form:
Some operator functions can also be used in a functional form:

>>> x = torch.tensor(0.6, requires_grad=True)
>>> matrix_fn = qml.matrix(qml.RX)
Expand All @@ -75,7 +95,7 @@ In the functional form, they are usually differentiable with respect to gate arg
>>> x.grad
tensor(-0.5910)

Some operator transform can also act on multiple operators, by passing
Some operator transforms can also act on multiple operators, by passing
quantum functions, QNodes or tapes:

>>> def circuit(theta):
Expand Down
28 changes: 27 additions & 1 deletion doc/releases/changelog-0.25.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,15 @@ of operators.

<h3>Improvements 📈</h3>

* A warning is emitted for measurements
- `qml.state`
- `qml.density_matrix`
- `qml.vn_entropy`
- `qml.mutual_info`
when using a device with finite shots or a shot list because the results of
these measurements are always analytic.
[(#2918)](https://github.com/PennyLaneAI/pennylane/pull/2918)

* The efficiency of the Hartree-Fock workflow has been improved by removing
repetitive steps.
[(#2850)](https://github.com/PennyLaneAI/pennylane/pull/2850)
Expand Down Expand Up @@ -624,7 +633,7 @@ of operators.
1. The custom device inherits from `DefaultQubit`, not `QubitDevice`.
2. The device implements custom methods in the simulation pipeline that are incompatible
with broadcasting (for example `expval`, `apply_operation` or `analytic_probability`).
3. The custom device maintains the flag `"supports_broadcasting": False` in its `capabilities`
3. The custom device maintains the flag `"supports_broadcasting": True` in its `capabilities`
dictionary *or* it overwrites `Device.batch_transform` without applying `broadcast_expand`
(or both).

Expand Down Expand Up @@ -700,6 +709,18 @@ of operators.

<h3>Bug fixes 🐞</h3>

* Cleans up interactions between operator arithmetic and batching by
testing supported cases and adding errors when batching is not supported.
[(#2900)](https://github.com/PennyLaneAI/pennylane/pull/2900)

* Fixed a bug where the parameter-shift rule wasn't defined for `qml.kUpCCGSD`.
[(#2913)](https://github.com/PennyLaneAI/pennylane/pull/2913)

* Reworked the Hermiticity check in `qml.Hermitian` by using `qml.math` calls
because calling `.conj()` on an `EagerTensor` from TensorFlow raised an
error.
[(#2895)](https://github.com/PennyLaneAI/pennylane/pull/2895)

* Updated IsingXY gate docstring.
[(#2858)](https://github.com/PennyLaneAI/pennylane/pull/2858)

Expand Down Expand Up @@ -746,6 +767,11 @@ of operators.
* Calling `qml.equal` with nested operators now raises a NotImplementedError.
[(#2877)](https://github.com/PennyLaneAI/pennylane/pull/2877)

* Returning `qml.sample()` or `qml.counts()` with other measurements of non-commuting observables
now raises a QuantumFunctionError (e.g., `return qml.expval(PauliX(wires=0)), qml.sample()`
now raises an error).
[(#2924)](https://github.com/PennyLaneAI/pennylane/pull/2924)

<h3>Contributors</h3>

This release contains contributions from (in alphabetical order):
Expand Down
1 change: 0 additions & 1 deletion pennylane/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@
is_commuting,
pattern_matching,
pattern_matching_optimization,
simplify,
)
from pennylane.ops.functions import *
from pennylane.optimize import *
Expand Down
76 changes: 75 additions & 1 deletion pennylane/_qubit_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,10 +312,22 @@ def execute(self, circuit, **kwargs):
# apply all circuit operations
self.apply(circuit.operations, rotations=circuit.diagonalizing_gates, **kwargs)

# generate computational basis samples
# generate computational basis samples and check for commutativity in sampled observables
if self.shots is not None or circuit.is_sampled:
self._samples = self.generate_samples()

raw_sampled_ops = False
for o in circuit.measurements:
if o.return_type in (qml.measurements.Sample, qml.measurements.Counts) and o.obs is None:
raw_sampled_ops = True
break

if raw_sampled_ops and circuit.diagonalizing_gates:
raise qml.QuantumFunctionError(
f"Computational basis measurements do not commute with some of the "
f"other measurements being performed:\n {circuit.measurements}"
)

ret_types = [m.return_type for m in circuit.measurements]
counts_exist = any(ret is qml.measurements.Counts for ret in ret_types)

Expand Down Expand Up @@ -401,6 +413,18 @@ def execute_new(self, circuit, **kwargs):
if self.shots is not None:
self._samples = self.generate_samples()

raw_sampled_ops = False
for o in circuit.measurements:
if o.return_type in (qml.measurements.Sample, qml.measurements.Counts) and o.obs is None:
raw_sampled_ops = True
break

if raw_sampled_ops and circuit.diagonalizing_gates:
raise qml.QuantumFunctionError(
f"Computational basis measurements do not commute with some of the "
f"other measurements being performed:\n {circuit.measurements}"
)

# compute the required statistics
if self._shot_vector is not None:

Expand Down Expand Up @@ -760,6 +784,14 @@ def statistics(self, observables, shot_range=None, bin_size=None):
" with other return types"
)

if self.shots is not None:
warnings.warn(
"Requested state or density matrix with finite shots; the returned "
"state information is analytic and is unaffected by sampling. To silence "
"this warning, set shots=None on the device.",
UserWarning,
)

# Check if the state is accessible and decide to return the state or the density
# matrix.
results.append(self.access_state(wires=obs.wires))
Expand All @@ -769,13 +801,31 @@ def statistics(self, observables, shot_range=None, bin_size=None):
raise qml.QuantumFunctionError(
"Returning the Von Neumann entropy is not supported when using custom wire labels"
)

if self.shots is not None:
warnings.warn(
"Requested Von Neumann entropy with finite shots; the returned "
"result is analytic and is unaffected by sampling. To silence "
"this warning, set shots=None on the device.",
UserWarning,
)

results.append(self.vn_entropy(wires=obs.wires, log_base=obs.log_base))

elif obs.return_type is MutualInfo:
if self.wires.labels != tuple(range(self.num_wires)):
raise qml.QuantumFunctionError(
"Returning the mutual information is not supported when using custom wire labels"
)

if self.shots is not None:
warnings.warn(
"Requested mutual information with finite shots; the returned "
"state information is analytic and is unaffected by sampling. To silence "
"this warning, set shots=None on the device.",
UserWarning,
)

wires0, wires1 = obs.raw_wires
results.append(
self.mutual_info(wires0=wires0, wires1=wires1, log_base=obs.log_base)
Expand Down Expand Up @@ -863,6 +913,14 @@ def statistics_new(self, observables, shot_range=None, bin_size=None):
" with other return types"
)

if self.shots is not None:
warnings.warn(
"Requested state or density matrix with finite shots; the returned "
"state information is analytic and is unaffected by sampling. To silence "
"this warning, set shots=None on the device.",
UserWarning,
)

# Check if the state is accessible and decide to return the state or the density
# matrix.
state = self.access_state(wires=obs.wires)
Expand All @@ -873,13 +931,29 @@ def statistics_new(self, observables, shot_range=None, bin_size=None):
raise qml.QuantumFunctionError(
"Returning the Von Neumann entropy is not supported when using custom wire labels"
)

if self.shots is not None:
warnings.warn(
"Requested Von Neumann entropy with finite shots; the returned "
"result is analytic and is unaffected by sampling. To silence "
"this warning, set shots=None on the device.",
UserWarning,
)
result = self.vn_entropy(wires=obs.wires, log_base=obs.log_base)

elif obs.return_type is MutualInfo:
if self.wires.labels != tuple(range(self.num_wires)):
raise qml.QuantumFunctionError(
"Returning the mutual information is not supported when using custom wire labels"
)

if self.shots is not None:
warnings.warn(
"Requested mutual information with finite shots; the returned "
"state information is analytic and is unaffected by sampling. To silence "
"this warning, set shots=None on the device.",
UserWarning,
)
wires0, wires1 = obs.raw_wires
result = self.mutual_info(wires0=wires0, wires1=wires1, log_base=obs.log_base)

Expand Down
11 changes: 10 additions & 1 deletion pennylane/devices/tests/test_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,16 @@ def circuit():

assert state is None
else:
circuit()

if dev.shots is not None:
with pytest.warns(
UserWarning,
match="Requested state or density matrix with finite shots; the returned",
):
circuit()
else:
circuit()

assert dev.state is not None

def test_returns_probs(self, device_kwargs):
Expand Down
Loading