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

defer_measurements raises errors for unsupported measurements #4701

Merged
merged 158 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
158 commits
Select commit Hold shift + click to select a range
64a3deb
Updated hash/eq
mudit2812 Aug 28, 2023
ed9d1f9
Updated pytest.ini
mudit2812 Aug 28, 2023
1c9a256
Updated changelog
mudit2812 Aug 28, 2023
593115d
Update doc/releases/changelog-dev.md
mudit2812 Aug 28, 2023
4380982
Removed warning imports
mudit2812 Aug 28, 2023
d7ab544
Merge branch 'master' into eq-hash
mudit2812 Aug 28, 2023
12e3fb4
Update tests
mudit2812 Aug 28, 2023
a052b7e
Fixed test
mudit2812 Aug 29, 2023
6647729
Added single MV support for MPs
mudit2812 Aug 29, 2023
b4ef716
Merge branch 'master' into eq-hash
mudit2812 Aug 29, 2023
31bef6e
Added docs; updated defer_measurements
mudit2812 Aug 29, 2023
855a194
Added mp tests
mudit2812 Aug 30, 2023
a003eb3
Added qnode test
mudit2812 Aug 30, 2023
29f93d9
Added deferred_measurements test
mudit2812 Aug 30, 2023
b8d1932
Merge branch 'master' into mcm-stats-1
mudit2812 Aug 30, 2023
e9f5200
Added changelog entry
mudit2812 Aug 30, 2023
096f90f
forgot to add name to changelog
mudit2812 Aug 30, 2023
6baf8ea
Fixed docs
mudit2812 Aug 30, 2023
362ac1c
Fixed test validation function
mudit2812 Aug 30, 2023
83fdd66
Fixed defer_measurementes
mudit2812 Aug 30, 2023
f0226df
Merge branch 'master' into mcm-stats-1
mudit2812 Aug 30, 2023
08d6dc2
Refactoring
mudit2812 Aug 30, 2023
e46e720
Reverted QNode changes
mudit2812 Aug 30, 2023
23d8fd3
Added example to changelog
mudit2812 Aug 30, 2023
dc418ab
Fixed example to changelog
mudit2812 Aug 30, 2023
10bde2e
Merge branch 'master' into eq-hash
mudit2812 Aug 30, 2023
655748a
Updated Hamiltonian.compare
mudit2812 Aug 31, 2023
37667e7
Merge branch 'master' into eq-hash
mudit2812 Aug 31, 2023
5e92495
Updated doc
mudit2812 Aug 31, 2023
b1f3896
Changed QNode back
mudit2812 Aug 31, 2023
a491511
Merge branch 'eq-hash' into mcm-stats-1
mudit2812 Aug 31, 2023
a4e8074
Fixed sample tests
mudit2812 Aug 31, 2023
802c7a0
Removed decimal
mudit2812 Aug 31, 2023
708baa5
Fixed counts
mudit2812 Sep 1, 2023
b82e49b
Merge branch 'master' into mcm-stats-1
mudit2812 Sep 1, 2023
6c2a232
Update changelog
mudit2812 Sep 5, 2023
5ebbc2e
separate DensityMatrixMP into its own measurement process (#4558)
timmysilv Sep 1, 2023
f10bfe4
add default.qubit.legacy and rename some test devices to prepare for …
timmysilv Sep 5, 2023
da51a83
StateMP accepts wires (#4570)
timmysilv Sep 5, 2023
361caf3
Deprecate fancy decorator syntax in batch transforms (#4457)
eddddddy Sep 6, 2023
126bd7b
Batch transforms are updated (#4440)
rmoyard Sep 6, 2023
ebb4d91
Update measurements tests for DQ2; create legacy tests folder (#4574)
timmysilv Sep 6, 2023
bcd09c4
Use fermi sentence in qchem dipole and number functions (#4546)
soranjh Sep 6, 2023
33ec1e6
fix np.random.seed usage (#4581)
timmysilv Sep 7, 2023
58fb45f
Remove qchem deprecated functionality for fermionic observables (#4556)
soranjh Sep 7, 2023
603074f
Update `DecompositionUndefinedError` for `Exp` class (#4571)
Jaybsoni Sep 8, 2023
8816391
Fix expand_tape_state_prep. (#4564)
vincentmr Sep 8, 2023
cc1cb0f
Merge branch 'master' into mcm-stats-1
mudit2812 Sep 8, 2023
2f48b93
Added counts legacy tests
mudit2812 Sep 8, 2023
f0d7ff8
Merge branch 'master' into mcm-stats-1
mudit2812 Sep 8, 2023
929b463
Fixing sample legacy tests
mudit2812 Sep 8, 2023
a6ce9aa
Reverted Hamiltonian.compare; linting
mudit2812 Sep 11, 2023
de5f3b1
Removed legacy tests
mudit2812 Sep 11, 2023
ffca318
Reverted sample legacy tests
mudit2812 Sep 11, 2023
8b22ca0
Update test to measure 3 wires
mudit2812 Sep 11, 2023
d86b085
Merge branch 'master' into mcm-stats-1
mudit2812 Sep 11, 2023
5bf5061
Updated MP eigvals
mudit2812 Sep 12, 2023
a7d0ebb
reformatting
mudit2812 Sep 12, 2023
d3b3057
Merge branch 'master' into mcm-stats-1
mudit2812 Sep 12, 2023
031b2d2
Reverted counts changes
mudit2812 Sep 12, 2023
74e896e
Removed error supression
mudit2812 Sep 13, 2023
150304d
Merging
mudit2812 Sep 13, 2023
53d7db5
Merge branch 'master' into mcm-stats-1
mudit2812 Sep 13, 2023
55c3a38
Updated measurements eigvals test
mudit2812 Sep 13, 2023
bd64ea9
AmplitudeEmbedding inherits from StatePrep (#4583)
timmysilv Sep 13, 2023
ba35f2a
Add support for offset in `qml.MPS` template (#4531)
obliviateandsurrender Sep 13, 2023
4c14d70
Fix copying the Select template (#4551)
DSGuala Sep 13, 2023
788fa67
Various changes for DQ2 to work (#4534)
timmysilv Sep 14, 2023
4ef3913
Update `op_transforms` (#4573)
mudit2812 Sep 14, 2023
ac42ff9
Make the device API not-experimental (#4594)
timmysilv Sep 15, 2023
c9c9fe3
get op batch size at runtime to match DQL (#4592)
timmysilv Sep 15, 2023
115b7bd
Removed unnecessary checks
mudit2812 Sep 15, 2023
74a8f75
Merge branch 'master' into mcm-stats-1
mudit2812 Sep 15, 2023
6a31c34
Adding postselection support
mudit2812 Sep 15, 2023
a63c802
Fixed qnode
mudit2812 Sep 15, 2023
34cb028
Added MeasurementValue to DQL supported observables
mudit2812 Sep 18, 2023
33bfaa5
update measure.py; add changelog for eigvals
mudit2812 Sep 18, 2023
0c32223
Fixed qnode
mudit2812 Sep 15, 2023
e7b332b
Added MeasurementValue to DQL supported observables
mudit2812 Sep 18, 2023
67d9ede
update measure.py; add changelog for eigvals
mudit2812 Sep 18, 2023
1e8c0de
Updated error message
mudit2812 Sep 18, 2023
c0ef20b
Added tests
mudit2812 Sep 18, 2023
b93563b
Added changelog
mudit2812 Sep 18, 2023
e8087a2
Fixed error
mudit2812 Sep 19, 2023
9117c8a
Updated simulate; added docs
mudit2812 Sep 19, 2023
129b563
Merge branch 'master' into mcm-stats-1
mudit2812 Sep 19, 2023
1d12308
Added docs to measurements.rst
mudit2812 Sep 19, 2023
b3b490d
fix torch take with axis=-1 (#4605)
timmysilv Sep 18, 2023
8321065
[CI] Bump jax version to v0.4.16 (#4612)
albi3ro Sep 19, 2023
8e421f5
TmpPauliRot still decomposes if the theta of zero is trainable (#4585)
timmysilv Sep 19, 2023
bf4dbb2
Update shot_adaptive to not mutate device shots (#4599)
timmysilv Sep 19, 2023
d8d269f
Tests always enable jax float64 (#4613)
albi3ro Sep 19, 2023
de83a59
`process_state` assumes flat, `state()` is always complex (#4602)
timmysilv Sep 19, 2023
6eb3d57
Register ParameterizedEvolution (#4598)
lillian542 Sep 19, 2023
a7c1294
Added docs to measurements.rst
mudit2812 Sep 19, 2023
4bfcac5
Added docs for nan values
mudit2812 Sep 19, 2023
01011d6
Merge branch 'mcm-stats-1' into mcm-post
mudit2812 Sep 19, 2023
25b9eff
Fixed doc error
mudit2812 Sep 19, 2023
cdf53d4
Updated measurement process; updated tests
mudit2812 Sep 20, 2023
1b4a7ae
Update tests
mudit2812 Sep 20, 2023
d1ad001
Update doc/introduction/measurements.rst
mudit2812 Sep 20, 2023
f0baf87
Update doc/releases/changelog-dev.md
mudit2812 Sep 20, 2023
227899b
Update pennylane/tape/qscript.py
mudit2812 Sep 20, 2023
4728585
Apply suggestions from code review
mudit2812 Sep 20, 2023
b857dc0
Addressing PR review
mudit2812 Sep 20, 2023
275b355
Add prng_key kwarg to new device API (#4596)
lillian542 Sep 19, 2023
c36f08c
Fix `qnn.TorchLayer` attributes (#4611)
albi3ro Sep 19, 2023
c782f78
bump jax version for docs (#4618)
albi3ro Sep 20, 2023
6c56a61
No qnode post processing on informative transforms (#4616)
rmoyard Sep 20, 2023
569e1aa
Removed unused imports
mudit2812 Sep 20, 2023
b5d9a5f
`default.qubit` returns the new `DefaultQubit` device (#4436)
timmysilv Sep 20, 2023
0a1b8c9
[skip ci] Added qml.math.is_nan
mudit2812 Sep 21, 2023
9cf3588
Update pennylane/transforms/defer_measurements.py
mudit2812 Sep 21, 2023
57d77bd
Make Measurements Pytrees (#4607)
albi3ro Sep 20, 2023
a4ae4c0
Converter for MPS DMRG wavefunctions (#4523)
Chiffafox Sep 20, 2023
d0240d8
Converter for SHCI wavefunction (#4524)
Chiffafox Sep 20, 2023
534601b
Updated measurements pytree stuff
mudit2812 Sep 21, 2023
e856749
Added tape splitting to defer_measurements
mudit2812 Sep 21, 2023
7ee28f7
Updated measure.py
mudit2812 Sep 21, 2023
240fbe2
Update returns.rst (#4617)
trbromley Sep 21, 2023
09baad0
fix and enable pulse gradient with broadcasting on new device (#4620)
timmysilv Sep 21, 2023
b0a2b16
Register `QuantumScript` and `QuantumTape` as pytrees (#4608)
albi3ro Sep 21, 2023
8996b4c
Merge branch 'master' into mcm-post
mudit2812 Sep 22, 2023
83613e0
Merge branch 'master' into mcm-post
mudit2812 Oct 2, 2023
c6f48e7
Added nan measurement
mudit2812 Oct 2, 2023
b5ade01
Fixed simulate; added tests
mudit2812 Oct 3, 2023
8579cce
Fixed mp errors
mudit2812 Oct 3, 2023
1ebc58d
Updated postselection measurement
mudit2812 Oct 4, 2023
4243dc3
Merge branch 'master' into mcm-post
mudit2812 Oct 4, 2023
e862d49
Updated defer_measurements tests
mudit2812 Oct 5, 2023
c1c763b
Reverted validation for zero probability. Need to update tests
mudit2812 Oct 6, 2023
beec97e
Merge branch 'master' into mcm-post
mudit2812 Oct 6, 2023
b6279f0
Lots of changes
mudit2812 Oct 16, 2023
05a32ea
Merge branch 'master' into mcm-post
mudit2812 Oct 16, 2023
adecaed
Merge branch 'master' into mcm-post
mudit2812 Oct 17, 2023
ddb00d0
Updated docs; added sampling tests
mudit2812 Oct 17, 2023
03807ac
[skip ci] adding tests; defer_measurements bug
mudit2812 Oct 17, 2023
160a771
Removed testing with shot vectors
mudit2812 Oct 17, 2023
d336ef0
Updated tests; fixed docs
mudit2812 Oct 17, 2023
94c1d70
Merge branch 'master' into mcm-post
mudit2812 Oct 17, 2023
54be0ca
Fixing/adding tests
mudit2812 Oct 18, 2023
dbd2a58
Fixed docs; linting
mudit2812 Oct 18, 2023
675a5f7
Fixed qnode tests; linting
mudit2812 Oct 18, 2023
6045241
Added coverage
mudit2812 Oct 18, 2023
9e149fe
More tests
mudit2812 Oct 18, 2023
d73a56d
[skip ci] Updated measurement docs
mudit2812 Oct 19, 2023
4f49f2b
Addressed PR review; tweaked docs
mudit2812 Oct 19, 2023
4fe2e25
Updated tests
mudit2812 Oct 19, 2023
e069ed4
Merge branch 'master' into mcm-post
mudit2812 Oct 19, 2023
f90a889
[skip ci] Fixing docs
mudit2812 Oct 20, 2023
8034037
Merge branch 'master' into mcm-post
mudit2812 Oct 20, 2023
d287798
[skip ci] Added errors
mudit2812 Oct 20, 2023
5066c28
[skip ci] Removed test case with `qml.state()`
mudit2812 Oct 20, 2023
1c5724c
[skip ci] Added link to changelog
mudit2812 Oct 20, 2023
0c53d59
[skip ci] Reordered preprocessing steps
mudit2812 Oct 20, 2023
48f56bf
[skip ci] Apply suggestions from code review
mudit2812 Oct 23, 2023
877eeca
Merge branch 'master' into mcm-state
mudit2812 Oct 23, 2023
a4cf441
Merge branch 'master' into mcm-state
mudit2812 Oct 23, 2023
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
5 changes: 4 additions & 1 deletion doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -382,9 +382,12 @@
decomposition.
[(#4675)](https://github.com/PennyLaneAI/pennylane/pull/4675)


<h3>Breaking changes 💔</h3>

* ``qml.defer_measurements`` now raises an error if a transformed circuit measures ``qml.probs``,
``qml.sample``, or ``qml.counts`` without any wires or obsrvable, or if it measures ``qml.state``.
[(#4701)](https://github.com/PennyLaneAI/pennylane/pull/4701)

* The device test suite now converts device kwargs to integers or floats if they can be converted to integers or floats.
[(#4640)](https://github.com/PennyLaneAI/pennylane/pull/4640)

Expand Down
2 changes: 1 addition & 1 deletion pennylane/devices/default_qubit.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,8 @@ def preprocess(
config = self._setup_execution_config(execution_config)
transform_program = TransformProgram()

transform_program.add_transform(qml.defer_measurements, device=self)
transform_program.add_transform(validate_device_wires, self.wires, name=self.name)
transform_program.add_transform(qml.defer_measurements, device=self)
transform_program.add_transform(
decompose, stopping_condition=stopping_condition, name=self.name
)
Expand Down
117 changes: 81 additions & 36 deletions pennylane/transforms/defer_measurements.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"""Code for the tape transform implementing the deferred measurement principle."""
from typing import Sequence, Callable
import pennylane as qml
from pennylane.measurements import MidMeasureMP
from pennylane.measurements import MidMeasureMP, ProbabilityMP, SampleMP, CountsMP
from pennylane.ops.op_math import ctrl

from pennylane.tape import QuantumTape
Expand All @@ -23,7 +23,66 @@
from pennylane.wires import Wires
from pennylane.queuing import QueuingManager

# pylint: disable=too-many-branches, too-many-statements
# pylint: disable=too-many-branches, protected-access


def _check_tape_validity(tape: QuantumTape):
"""Helper function to check that the tape is valid."""
cv_types = (qml.operation.CVOperation, qml.operation.CVObservable)
ops_cv = any(isinstance(op, cv_types) and op.name != "Identity" for op in tape.operations)
obs_cv = any(
isinstance(getattr(op, "obs", None), cv_types)
and not isinstance(getattr(op, "obs", None), qml.Identity)
for op in tape.measurements
)
if ops_cv or obs_cv:
raise ValueError("Continuous variable operations and observables are not supported.")

for mp in tape.measurements:
if isinstance(mp, (CountsMP, ProbabilityMP, SampleMP)) and not (
mp.obs or mp._wires or mp.mv
):
raise ValueError(
f"Cannot use {mp.__class__.__name__} as a measurement without specifying wires "
"when using qml.defer_measurements. Deferred measurements can occur "
"automatically when using mid-circuit measurements on a device that does not "
"support them."
)

if mp.__class__.__name__ == "StateMP":
raise ValueError(
"Cannot use StateMP as a measurement when using qml.defer_measurements. "
"Deferred measurements can occur automatically when using mid-circuit "
"measurements on a device that does not support them."
)


def _collect_mid_measure_info(tape: QuantumTape):
"""Helper function to collect information related to mid-circuit measurements in the tape."""

# Find wires that are reused after measurement
measured_wires = []
reused_measurement_wires = set()
any_repeated_measurements = False
is_postselecting = False

for op in tape.operations:
if isinstance(op, MidMeasureMP):
if op.postselect is not None:
is_postselecting = True
if op.reset:
reused_measurement_wires.add(op.wires[0])

if op.wires[0] in measured_wires:
any_repeated_measurements = True
measured_wires.append(op.wires[0])

else:
reused_measurement_wires = reused_measurement_wires.union(
set(measured_wires).intersection(op.wires.toset())
)

return measured_wires, reused_measurement_wires, any_repeated_measurements, is_postselecting


def null_postprocessing(results):
Expand Down Expand Up @@ -68,12 +127,18 @@ def defer_measurements(tape: QuantumTape, **kwargs) -> (Sequence[QuantumTape], C

.. note::

When applying the transform on a quantum function that returns
:func:`~pennylane.state` as the terminal measurement or contains the
When applying the transform on a quantum function that contains the
:class:`~.Snapshot` instruction, state information corresponding to
simulating the transformed circuit will be obtained. No
post-measurement states are considered.

.. warning::

:func:`~.pennylane.state` is not supported with the ``defer_measurements`` transform.
Additionally, :func:`~.pennylane.probs`, :func:`~.pennylane.sample` and
:func:`~.pennylane.counts` can only be used with ``defer_measurements`` if wires
or an observable are explicitly specified.

Args:
tape (.QuantumTape): a quantum tape

Expand Down Expand Up @@ -136,45 +201,25 @@ def func(x, y):
>>> func(*pars)
tensor([0.76960924, 0.13204407, 0.08394415, 0.01440254], requires_grad=True)
"""
# pylint: disable=protected-access

if not any(isinstance(o, MidMeasureMP) for o in tape.operations):
return (tape,), null_postprocessing

cv_types = (qml.operation.CVOperation, qml.operation.CVObservable)
ops_cv = any(isinstance(op, cv_types) and op.name != "Identity" for op in tape.operations)
obs_cv = any(
isinstance(getattr(op, "obs", None), cv_types)
and not isinstance(getattr(op, "obs", None), qml.Identity)
for op in tape.measurements
)
if ops_cv or obs_cv:
raise ValueError("Continuous variable operations and observables are not supported.")
_check_tape_validity(tape)

device = kwargs.get("device", None)

device = kwargs.get("device", None)

new_operations = []

# Find wires that are reused after measurement
measured_wires = []
reused_measurement_wires = set()
repeated_measurement_wire = False
is_postselecting = False

for op in tape.operations:
if isinstance(op, MidMeasureMP):
if op.postselect is not None:
is_postselecting = True
if op.reset:
reused_measurement_wires.add(op.wires[0])

if op.wires[0] in measured_wires:
repeated_measurement_wire = True
measured_wires.append(op.wires[0])

else:
reused_measurement_wires = reused_measurement_wires.union(
set(measured_wires).intersection(op.wires.toset())
)
(
measured_wires,
reused_measurement_wires,
any_repeated_measurements,
is_postselecting,
) = _collect_mid_measure_info(tape)

if is_postselecting and device is not None and not isinstance(device, qml.devices.DefaultQubit):
raise ValueError(f"Postselection is not supported on the {device} device.")
Expand All @@ -183,7 +228,7 @@ def func(x, y):
# classically controlled operations
control_wires = {}
cur_wire = (
max(tape.wires) + 1 if reused_measurement_wires or repeated_measurement_wire else None
max(tape.wires) + 1 if reused_measurement_wires or any_repeated_measurements else None
)

for op in tape.operations:
Expand Down Expand Up @@ -257,7 +302,7 @@ def _add_control_gate(op, control_wires):
control = [control_wires[m.id] for m in op.meas_val.measurements]
new_ops = []

for branch, value in op.meas_val._items(): # pylint: disable=protected-access
for branch, value in op.meas_val._items():
if value:
qscript = qml.tape.make_qscript(
ctrl(
Expand Down
2 changes: 0 additions & 2 deletions tests/devices/default_qubit/test_default_qubit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1650,7 +1650,6 @@ class TestPostselection:
qml.expval(qml.PauliZ(0)),
qml.var(qml.PauliZ(0)),
qml.probs(wires=[0, 1]),
qml.state(),
qml.density_matrix(wires=0),
qml.purity(0),
qml.vn_entropy(0),
Expand Down Expand Up @@ -1800,7 +1799,6 @@ def circ_postselect(theta):
(qml.expval(qml.PauliZ(0)), "autograd", True),
(qml.var(qml.PauliZ(0)), "autograd", True),
(qml.probs(wires=[0, 1]), "autograd", True),
(qml.state(), "autograd", True),
(qml.density_matrix(wires=0), "autograd", True),
(qml.purity(0), "numpy", True),
(qml.vn_entropy(0), "numpy", False),
Expand Down
23 changes: 20 additions & 3 deletions tests/transforms/test_defer_measurements.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,23 @@ def circ():
_ = circ()


@pytest.mark.parametrize(
"mp, err_msg",
[
(qml.state(), "Cannot use StateMP as a measurement when"),
(qml.probs(), "Cannot use ProbabilityMP as a measurement without"),
(qml.sample(), "Cannot use SampleMP as a measurement without"),
(qml.counts(), "Cannot use CountsMP as a measurement without"),
],
)
def test_unsupported_measurements(mp, err_msg):
"""Test that using unsupported measurements raises an error."""
tape = qml.tape.QuantumScript([MidMeasureMP(0)], [mp])

with pytest.raises(ValueError, match=err_msg):
_, _ = qml.defer_measurements(tape)


class TestQNode:
"""Test that the transform integrates well with QNodes."""

Expand Down Expand Up @@ -1467,7 +1484,7 @@ def test_custom_wire_labels_allowed_without_reset():
qml.Hadamard("a")
ma = qml.measure("a", reset=False)
qml.cond(ma, qml.PauliX)("b")
qml.state()
qml.probs(wires="a")

tape = qml.tape.QuantumScript.from_queue(q)
tapes, _ = qml.defer_measurements(tape)
Expand All @@ -1476,7 +1493,7 @@ def test_custom_wire_labels_allowed_without_reset():
assert len(tape) == 3
assert qml.equal(tape[0], qml.Hadamard("a"))
assert qml.equal(tape[1], qml.CNOT(["a", "b"]))
assert qml.equal(tape[2], qml.state())
assert qml.equal(tape[2], qml.probs(wires="a"))


def test_custom_wire_labels_fails_with_reset():
Expand All @@ -1485,7 +1502,7 @@ def test_custom_wire_labels_fails_with_reset():
qml.Hadamard("a")
ma = qml.measure("a", reset=True)
qml.cond(ma, qml.PauliX)("b")
qml.state()
qml.probs(wires="a")

tape = qml.tape.QuantumScript.from_queue(q)
with pytest.raises(TypeError, match="can only concatenate str"):
Expand Down
Loading