Skip to content

Commit

Permalink
Raise warning in Operator __eq__ and __hash__ about change in beh…
Browse files Browse the repository at this point in the history
…aviour (#4144)

* Updated Operator

* Added tests

* Updated warning

* black

* Updated warning text

* black

* Update doc/development/deprecations.rst

* Updated docs, tests

* Updated deprecations.rst

* Fixing tests

* Updated tests and warnings

* Pylint

* Testing warnings

* Testing changes

* Updated tests

* testing what breaks

* Checking tests

* Testing changes

* Testing changes to operator __eq__

* Updated until `nodes_between`

* Updated metric tensor, circuit graph

* Updating `qml.equal`

* Linters

* Updated tape tests

* Added coverage

* Updates changelog

* Removed changes to __eq__ and __hash__

* Update pennylane/operation.py

Co-authored-by: Matthew Silverman <matthews@xanadu.ai>

* Testing changes to operator __eq__

* Updated until `nodes_between`

* Updated metric tensor, circuit graph

* Updating `qml.equal`

* Linters

* Fixes for new autoray version (#4396)

* Fixes for new autoray version

* unused import

* Use if instead of try-except

* Fix case of two torch tensors

* Updated tape tests

* Add ability to apply `TransformProgram` to batch of tapes (#4364)

* Draft structure

* draf exec

* Simple execute

* Update

* More tests

* Update

* Update exec

* Pylint and black

* Update tests

* Update more tests

* More tests

* changelog

* Coverage

* Cover fix

* pylint

* Pylint

* Pylint tests

* proposed changes to transform program integration

* oops

* add to legacy, remove cotransform support

* just transform program call component

* just transform program call component

* no longer support cotransforms, fix _batch_postprocessing

* some more testing

* test null postprocessing function

* docstring, rename batch_slices to slices, black

* Apply suggestions from code review

Co-authored-by: Matthew Silverman <matthews@xanadu.ai>

---------

Co-authored-by: rmoyard <rmoyard@gmail.com>
Co-authored-by: Matthew Silverman <matthews@xanadu.ai>

* torch qnode integration with DefaultQubit2 (#4392)

* copy-paste torch file; replace device in most places

* make tests work; little changes in pennylane

* pylint fix

* changelog

* update test name and docstring for hamiltonian_expand

* minimal test for single-shot bugfix

* Added coverage

* Updates changelog

* Removed changes to __eq__ and __hash__

* Update pennylane/operation.py

Co-authored-by: Matthew Silverman <matthews@xanadu.ai>

* Updated deprecations to 0.32

* Added warnings

* Trigger CI

* Removed docstrings

* Added correctness test

* Trigger CI

---------

Co-authored-by: Tom Bromley <49409390+trbromley@users.noreply.github.com>
Co-authored-by: Matthew Silverman <matthews@xanadu.ai>
Co-authored-by: Edward Jiang <34989448+eddddddy@users.noreply.github.com>
Co-authored-by: Christina Lee <christina@xanadu.ai>
Co-authored-by: rmoyard <rmoyard@gmail.com>
  • Loading branch information
6 people authored Jul 28, 2023
1 parent 7bc2e0e commit c1b9aa2
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 1 deletion.
22 changes: 22 additions & 0 deletions doc/development/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,28 @@ Pending deprecations
some_qfunc(params)
return qml.expval(Hamiltonian)
* The behaviour of ``Operator.__eq__`` and ``Operator.__hash__`` will be updated soon. Their documentation
has been updated to reflect the incoming changes.

The upcoming changes to operator equality will allow users to use operator equality the same way as
with ``qml.equal``. With the changes to hashing, unique operators that are equal will have the same
hash. These changes will allow behaviour such as the following:

>>> qml.RX(0.1, wires=0) == qml.RX(0.1, wires=0)
True
>>> {qml.PauliZ(0), qml.PauliZ(0)}
{PauliZ(wires=[0])}

Meanwhile, the current behaviour is shown below:

>>> qml.RX(0.1, wires=0) == qml.RX(0.1, wires=0)
False
>>> {qml.PauliZ(0), qml.PauliZ(0)}
{PauliZ(wires=[0]), PauliZ(wires=[0])}

- Added in v0.32
- Behaviour will change in v0.33

* The public methods of ``DefaultQubit`` are pending changes to
follow the new device API, as used in ``DefaultQubit2``.

Expand Down
4 changes: 4 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@
been deprecated. Please use `QuantumScript.bind_new_parameters` instead.
[(#4346)](https://github.com/PennyLaneAI/pennylane/pull/4346)

* `Operator.__eq__` and `Operator.__hash__` will now raise warnings to reflect upcoming
changes to operator equality and hashing.
[(#4144)](https://github.com/PennyLaneAI/pennylane/pull/4144)

<h3>Documentation 📝</h3>

* The `qml.pulse.transmon_interaction` and `qml.pulse.transmon_drive` documentation has been updated.
Expand Down
25 changes: 25 additions & 0 deletions pennylane/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,31 @@ def hash(self):
)
)

# pylint: disable=useless-super-delegation
def __eq__(self, other):
warnings.warn(
"The behaviour of operator equality will be updated soon. Currently, op1 == op2 is "
"True if op1 and op2 are the same object. Soon, op1 == op2 will be equivalent to "
"qml.equal(op1, op2). To continue using operator equality in its current state, "
"use 'op1 is op2'.",
UserWarning,
)

return super().__eq__(other)

# pylint: disable=useless-super-delegation
def __hash__(self):
warnings.warn(
"The behaviour of operator hashing will be updated soon. Currently, each operator "
"instance has a unique hash. Soon, an operator's hash will be determined by the "
"combined hash of the name, wires, parameters and hyperparameters of the operator. "
"To continue using operator hashing in its current state, wrap the operator inside "
"a qml.queuing.WrappedObj instance.",
UserWarning,
)

return super().__hash__()

@staticmethod
def compute_matrix(*params, **hyperparams): # pylint:disable=unused-argument
r"""Representation of the operator as a canonical matrix in the computational basis (static method).
Expand Down
3 changes: 2 additions & 1 deletion tests/pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ filterwarnings =
ignore:Casting complex values to real::autograd.numpy.numpy_wrapper
ignore:Casting complex values to real discards the imaginary part:UserWarning:torch.autograd
ignore:Call to deprecated create function:DeprecationWarning
ignore:the imp module is deprecated:DeprecationWarning
ignore:the imp module is deprecated:DeprecationWarning
error:The behaviour of operator:UserWarning
52 changes: 52 additions & 0 deletions tests/test_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,58 @@ def __init__(self, wires, basis_state=None): # pylint:disable=super-init-not-ca
state = [0, 1, 0]
assert MyOp(wires=1, basis_state=state).hyperparameters["basis_state"] == state

def test_eq_warning(self):
"""Test that a warning is raised when two operators are compared for equality
using `==`."""

class DummyOp(qml.operation.Operator):
num_wires = 1

op1 = DummyOp(0)
op2 = DummyOp(0)

with pytest.warns(UserWarning, match="The behaviour of operator equality"):
_ = op1 == op2

def test_eq_correctness(self):
"""Test that using `==` on two equivalent operators is True when both operators
are the same object and False otherwise."""

class DummyOp(qml.operation.Operator):
num_wires = 1

op1 = DummyOp(0)
op2 = DummyOp(0)

with pytest.warns(UserWarning, match="The behaviour of operator equality"):
assert op1 == op1 # pylint: disable=comparison-with-itself
assert op1 != op2

def test_hash_warning(self):
"""Test that a warning is raised when an operator's hash is used."""

class DummyOp(qml.operation.Operator):
num_wires = 1

op = DummyOp(0)

with pytest.warns(UserWarning, match="The behaviour of operator hashing"):
_ = hash(op)

def test_hash_correctness(self):
"""Test that the hash of two equivalent operators is the same when both operators
are the same object and different otherwise."""

class DummyOp(qml.operation.Operator):
num_wires = 1

op1 = DummyOp(0)
op2 = DummyOp(0)

with pytest.warns(UserWarning, match="The behaviour of operator hash"):
assert len({op1, op1}) == 1
assert len({op1, op2}) == 2


class TestPytreeMethods:
def test_pytree_defaults(self):
Expand Down

0 comments on commit c1b9aa2

Please sign in to comment.