From c162b1aba83a585e7f51b125a3bf4428bb1cf71b Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 10:48:18 +0100 Subject: [PATCH 01/35] feat (Operator): :sparkles: __mul__ dunder method. --- pennylane/operation.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pennylane/operation.py b/pennylane/operation.py index 7283612f4ca..8492908435b 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1222,6 +1222,22 @@ def __add__(self, other): __radd__ = __add__ + def __mul__(self, other): + """The product operation between Operators and/or scalars.""" + if isinstance(other, numbers.Number): + return qml.ops.SProd(scalar=other, base=self) # pylint: disable=no-member + if isinstance(other, Operator): + return qml.ops.Prod(self, other) # pylint: disable=no-member + raise ValueError(f"Cannot multiply Operator and {type(other)}") + + def __rmul__(self, other): + """The product operation between Operators and/or scalars.""" + if isinstance(other, numbers.Number): + return qml.ops.SProd(scalar=other, base=self) # pylint: disable=no-member + if isinstance(other, Operator): + return qml.ops.Prod(other, self) # pylint: disable=no-member + raise ValueError(f"Cannot multiply Operator and {type(other)}") + def __sub__(self, other): """The substraction operation of Operator-Operator objects and Operator-scalar.""" if isinstance(other, (Operator, numbers.Number)): From c3273af86cafa15a375890a61297e0f52c68af37 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 11:15:48 +0100 Subject: [PATCH 02/35] test (Operator): :test_tube: Compare operators. --- tests/test_operation.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/test_operation.py b/tests/test_operation.py index cf7db40b170..ab68446160b 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -780,9 +780,14 @@ class DummyOp(qml.operation.Operation): def test_sum_with_scalar(self): """Test the __sum__ dunder method with a scalar value.""" sum_op = 5 + qml.PauliX(0) - final_op = qml.ops.Sum(qml.ops.s_prod(5, qml.Identity(0)), qml.PauliX(0)) + final_op = qml.ops.Sum(qml.PauliX(0), qml.ops.s_prod(5, qml.Identity(0))) # TODO: Use qml.equal when fixed. - assert np.allclose(sum_op.matrix(), final_op.matrix(), rtol=0) + assert isinstance(sum_op, qml.ops.Sum) + for s1, s2 in zip(sum_op.summands, final_op.summands): + assert s1.name == s2.name + assert s1.wires == s2.wires + assert s1.data == s2.data + assert np.allclose(a=sum_op.matrix(), b=final_op.matrix(), rtol=0) def test_dunder_methods(self): """Test the __sub__, __rsub__ and __neg__ dunder methods.""" From 3e487be8d9d1be66ef16ab6177c5c49e3ac819c7 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 11:24:10 +0100 Subject: [PATCH 03/35] test (Operator): :test_tube: Add __mul__ test. --- pennylane/operation.py | 16 ++++++++++++---- tests/test_operation.py | 25 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/pennylane/operation.py b/pennylane/operation.py index 8492908435b..02a80b4c2e1 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1729,12 +1729,20 @@ def __add__(self, other): def __mul__(self, a): r"""The scalar multiplication operation between a scalar and an Observable/Tensor.""" if isinstance(a, (int, float)): - return qml.Hamiltonian([a], [self], simplify=True) + try: + return super().__mul__(other=a) + except ValueError as e: + raise ValueError(f"Cannot multiply Observable by {type(a)}") from e - raise ValueError(f"Cannot multiply Observable by {type(a)}") - - __rmul__ = __mul__ + def __rmul__(self, a): + r"""The scalar multiplication operation between a scalar and an Observable/Tensor.""" + if isinstance(a, (int, float)): + return qml.Hamiltonian([a], [self], simplify=True) + try: + return super().__rmul__(other=a) + except ValueError as e: + raise ValueError(f"Cannot multiply Observable by {type(a)}") from e def __sub__(self, other): r"""The subtraction operation between Observables/Tensors/qml.Hamiltonian objects.""" diff --git a/tests/test_operation.py b/tests/test_operation.py index ab68446160b..cbd0c162277 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -798,6 +798,31 @@ def test_dunder_methods(self): neg_op = -qml.PauliX(0) assert np.allclose(a=neg_op.matrix(), b=np.array([[0, -1], [-1, 0]]), rtol=0) + def test_mul_with_scalar(self): + """Test the __mul__ dunder method with a scalar value.""" + sprod_op = 4 * qml.RX(1, 0) + sprod_op2 = qml.RX(1, 0) * 4 + final_op = qml.ops.SProd(scalar=4, base=qml.RX(1, 0)) + assert isinstance(sprod_op, qml.ops.SProd) + assert sprod_op.name == sprod_op2.name + assert sprod_op.wires == sprod_op2.wires + assert sprod_op.data == sprod_op2.data + assert sprod_op.name == final_op.name + assert sprod_op.wires == final_op.wires + assert sprod_op.data == final_op.data + assert np.allclose(sprod_op.matrix(), sprod_op2.matrix(), rtol=0) + assert np.allclose(sprod_op.matrix(), final_op.matrix(), rtol=0) + + def test_mul_with_operator(self): + """Test the __mul__ dunder method with an operator.""" + prod_op = qml.PauliX(0) * qml.RX(1, 0) + final_op = qml.ops.Prod(qml.PauliX(0), qml.RX(1, 0)) + assert isinstance(prod_op, qml.ops.Prod) + assert prod_op.name == final_op.name + assert prod_op.wires == final_op.wires + assert prod_op.data == final_op.data + assert np.allclose(prod_op.matrix(), final_op.matrix(), rtol=0) + class TestInverse: """Test inverse of operations""" From 358b8586a8eeafa1abe741cbfe02a95d03de1005 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 11:28:07 +0100 Subject: [PATCH 04/35] chore (changelog): :pencil2: Add feature to changelog. --- doc/releases/changelog-dev.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 4468848df7b..d04f1b7e355 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -69,7 +69,7 @@ The resource estimation algorithms are implemented as classes inherited from the `Operation` class. The number of non-Clifford gates and logical qubits for implementing each algorithm can be - estimated by initiating the class for a given system. For the first quantization algorithm, the + estimated by initiating the class for a given system. For the first quantization algorithm, the number of plane waves, number of electrons and the unit cell volume (in atomic units) are needed to initiate the `FirstQuantization` class. The resource can then be estimated as @@ -118,7 +118,7 @@ The methods of the `FirstQuantization` and the `DoubleFactorization` classes can be also accessed individually. For instance, the logical qubits can be computed by providing the inputs needed for - this estimation without initiating the class. + this estimation without initiating the class. ```python n = 100000 @@ -274,7 +274,7 @@ ``` * New PennyLane-inspired `sketch` and `sketch_dark` styles are now available for - drawing circuit diagram graphics. + drawing circuit diagram graphics. [(#2709)](https://github.com/PennyLaneAI/pennylane/pull/2709) * Added `QutritDevice` as an abstract base class for qutrit devices. @@ -296,7 +296,6 @@ [0.5 0.5 0. ] ``` - **Operator Arithmetic:** * Adds the `Controlled` symbolic operator to represent a controlled version of any @@ -350,7 +349,7 @@ * Added `__add__` and `__pow__` dunder methods to the `qml.operation.Operator` class so that users can combine operators more naturally. [(#2807)](https://github.com/PennyLaneAI/pennylane/pull/2807) - ```python + ```pycon >>> summed_op = qml.RX(phi=1.23, wires=0) + qml.RZ(phi=3.14, wires=0) >>> summed_op RX(1.23, wires=[0]) + RZ(3.14, wires=[0]) @@ -359,6 +358,15 @@ RZ**2(1.0, wires=[0]) ``` +* Added `__mul__` dunder method to the `qml.operation.Operator` class so that users can combine + operators more naturally. [(#2891)](https://github.com/PennyLaneAI/pennylane/pull/2891) + + ```pycon + >>> prod_op = qml.PauliX(0) * qml.PauliX(1) + >>> prod_op + PauliX(wires=[0]) @ PauliZ(wires=[1]) + ``` + * Added support for addition of operators and scalars. [(#2849)](https://github.com/PennyLaneAI/pennylane/pull/2849) ```pycon From f48e700b26f3f3cd6c52396ea769f33cf9edb81d Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 11:35:51 +0100 Subject: [PATCH 05/35] test (Operator): :test_tube: Add test. --- tests/test_operation.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test_operation.py b/tests/test_operation.py index cbd0c162277..3811e01a1c4 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -823,6 +823,11 @@ def test_mul_with_operator(self): assert prod_op.data == final_op.data assert np.allclose(prod_op.matrix(), final_op.matrix(), rtol=0) + def test_mul_with_not_supported_object_raises_error(self): + """Test that the __mul__ dunder method raises an error when using a non-supported object.""" + with pytest.raises(ValueError, match="Cannot multiply Observable by"): + _ = "dummy" * qml.PauliX(0) + class TestInverse: """Test inverse of operations""" From 4bb6d9f22d2fb7fbc8e4b1c25650825930e33f03 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 11:36:35 +0100 Subject: [PATCH 06/35] test (Operator): :test_tube: Add test. --- tests/test_operation.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_operation.py b/tests/test_operation.py index 3811e01a1c4..2861c9ce7e7 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -827,6 +827,8 @@ def test_mul_with_not_supported_object_raises_error(self): """Test that the __mul__ dunder method raises an error when using a non-supported object.""" with pytest.raises(ValueError, match="Cannot multiply Observable by"): _ = "dummy" * qml.PauliX(0) + with pytest.raises(ValueError, match="Cannot multiply Observable by"): + _ = qml.PauliX(0) * "dummy" class TestInverse: From b1ca393d4c01df610c5098443e99e8eff666d0e7 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 12:29:19 +0100 Subject: [PATCH 07/35] chore (changelog): :pencil2: Add feature to changelog. --- doc/releases/changelog-dev.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index d04f1b7e355..aebf80b2cf6 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -358,8 +358,9 @@ RZ**2(1.0, wires=[0]) ``` -* Added `__mul__` dunder method to the `qml.operation.Operator` class so that users can combine - operators more naturally. [(#2891)](https://github.com/PennyLaneAI/pennylane/pull/2891) +* Added `__mul__` and `__rmul__` dunder methods to the `qml.operation.Operator` class so + that users can combine operators more naturally. + [(#2891)](https://github.com/PennyLaneAI/pennylane/pull/2891) ```pycon >>> prod_op = qml.PauliX(0) * qml.PauliX(1) From b9fd66386e9f3b4768d25a588b5f2649baeb8e13 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 12:40:30 +0100 Subject: [PATCH 08/35] refactor (Operation): :recycle: Remove dead line. --- pennylane/operation.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pennylane/operation.py b/pennylane/operation.py index 02a80b4c2e1..06479edd8a9 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1234,8 +1234,6 @@ def __rmul__(self, other): """The product operation between Operators and/or scalars.""" if isinstance(other, numbers.Number): return qml.ops.SProd(scalar=other, base=self) # pylint: disable=no-member - if isinstance(other, Operator): - return qml.ops.Prod(other, self) # pylint: disable=no-member raise ValueError(f"Cannot multiply Operator and {type(other)}") def __sub__(self, other): From 06c488bc7466eb6d8753e696f5fdfb985ead0749 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 12:42:01 +0100 Subject: [PATCH 09/35] docs: :memo: Fix docs. --- pennylane/operation.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pennylane/operation.py b/pennylane/operation.py index 06479edd8a9..ffe72f8f1aa 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1234,6 +1234,8 @@ def __rmul__(self, other): """The product operation between Operators and/or scalars.""" if isinstance(other, numbers.Number): return qml.ops.SProd(scalar=other, base=self) # pylint: disable=no-member + # FIXME: I believe we don't need to add the case where `other` is an Operator, given + # that then __mul__ will be called. Anyone disagrees? raise ValueError(f"Cannot multiply Operator and {type(other)}") def __sub__(self, other): From b550bc2d88fa5c01ff4e39e80a62962b039d56aa Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 12:46:01 +0100 Subject: [PATCH 10/35] refactor (Operation): :recycle: Remove __rmul__. --- pennylane/operation.py | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/pennylane/operation.py b/pennylane/operation.py index ffe72f8f1aa..9734407e8f5 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1230,13 +1230,7 @@ def __mul__(self, other): return qml.ops.Prod(self, other) # pylint: disable=no-member raise ValueError(f"Cannot multiply Operator and {type(other)}") - def __rmul__(self, other): - """The product operation between Operators and/or scalars.""" - if isinstance(other, numbers.Number): - return qml.ops.SProd(scalar=other, base=self) # pylint: disable=no-member - # FIXME: I believe we don't need to add the case where `other` is an Operator, given - # that then __mul__ will be called. Anyone disagrees? - raise ValueError(f"Cannot multiply Operator and {type(other)}") + __rmul__ = __mul__ def __sub__(self, other): """The substraction operation of Operator-Operator objects and Operator-scalar.""" @@ -1735,14 +1729,7 @@ def __mul__(self, a): except ValueError as e: raise ValueError(f"Cannot multiply Observable by {type(a)}") from e - def __rmul__(self, a): - r"""The scalar multiplication operation between a scalar and an Observable/Tensor.""" - if isinstance(a, (int, float)): - return qml.Hamiltonian([a], [self], simplify=True) - try: - return super().__rmul__(other=a) - except ValueError as e: - raise ValueError(f"Cannot multiply Observable by {type(a)}") from e + __rmul__ = __mul__ def __sub__(self, other): r"""The subtraction operation between Observables/Tensors/qml.Hamiltonian objects.""" From cb16160876f425b2e71b5afe411f734be494bf1a Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 15:15:58 +0100 Subject: [PATCH 11/35] refactor (Hamiltonian): :recycle: Remove super call. --- pennylane/ops/qubit/hamiltonian.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pennylane/ops/qubit/hamiltonian.py b/pennylane/ops/qubit/hamiltonian.py index e84452a9e5a..f4dc23dc637 100644 --- a/pennylane/ops/qubit/hamiltonian.py +++ b/pennylane/ops/qubit/hamiltonian.py @@ -590,10 +590,8 @@ def __add__(self, H): ) ops.append(H) return qml.Hamiltonian(coeffs, ops, simplify=True) - try: - return super().__add__(other=H) - except ValueError as e: - raise ValueError(f"Cannot add Hamiltonian and {type(H)}") from e + + raise ValueError(f"Cannot add Hamiltonian and {type(H)}") __radd__ = __add__ From 3decee5952715e8a3d61b3378f1efa2875076572 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 15:16:37 +0100 Subject: [PATCH 12/35] feat (Operator): :sparkles: __matmul__ dunder method. --- pennylane/operation.py | 15 +++++++++++---- tests/test_operation.py | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/pennylane/operation.py b/pennylane/operation.py index 9734407e8f5..7b74f002980 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1223,15 +1223,19 @@ def __add__(self, other): __radd__ = __add__ def __mul__(self, other): - """The product operation between Operators and/or scalars.""" + """The scalar multiplication between scalars and Operators.""" if isinstance(other, numbers.Number): return qml.ops.SProd(scalar=other, base=self) # pylint: disable=no-member - if isinstance(other, Operator): - return qml.ops.Prod(self, other) # pylint: disable=no-member raise ValueError(f"Cannot multiply Operator and {type(other)}") __rmul__ = __mul__ + def __matmul__(self, other): + """The product operation between Operator objects.""" + if isinstance(other, Operator): + return qml.ops.Prod(self, other) # pylint: disable=no-member + raise ValueError(f"Cannot multiply Operator and {type(other)}") + def __sub__(self, other): """The substraction operation of Operator-Operator objects and Operator-scalar.""" if isinstance(other, (Operator, numbers.Number)): @@ -1645,7 +1649,10 @@ def __matmul__(self, other): if isinstance(other, Observable): return Tensor(self, other) - raise ValueError("Can only perform tensor products between observables.") + try: + return super().__matmul__(other=other) + except ValueError as e: + raise ValueError("Can only perform tensor products between observables.") from e def _obs_data(self): r"""Extracts the data from a Observable or Tensor and serializes it in an order-independent fashion. diff --git a/tests/test_operation.py b/tests/test_operation.py index 2861c9ce7e7..b7e50a1ddbe 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -815,7 +815,7 @@ def test_mul_with_scalar(self): def test_mul_with_operator(self): """Test the __mul__ dunder method with an operator.""" - prod_op = qml.PauliX(0) * qml.RX(1, 0) + prod_op = qml.PauliX(0) @ qml.RX(1, 0) final_op = qml.ops.Prod(qml.PauliX(0), qml.RX(1, 0)) assert isinstance(prod_op, qml.ops.Prod) assert prod_op.name == final_op.name From 6bd9863c5b6960ae7075036d2e8b93453320500b Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 15:21:28 +0100 Subject: [PATCH 13/35] chore (changelog): :pencil2: Modify changelog. --- doc/releases/changelog-dev.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index aebf80b2cf6..f8312c29a84 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -358,14 +358,17 @@ RZ**2(1.0, wires=[0]) ``` -* Added `__mul__` and `__rmul__` dunder methods to the `qml.operation.Operator` class so +* Added `__mul__` and `__matmul__` dunder methods to the `qml.operation.Operator` class so that users can combine operators more naturally. [(#2891)](https://github.com/PennyLaneAI/pennylane/pull/2891) ```pycon - >>> prod_op = qml.PauliX(0) * qml.PauliX(1) + >>> prod_op = qml.PauliX(0) @ qml.PauliX(1) >>> prod_op PauliX(wires=[0]) @ PauliZ(wires=[1]) + >>> sprod_op = 6 * qml.RX(1, 0) + >>> sprod_op + 6*(RX(1, wires=[0])) ``` * Added support for addition of operators and scalars. [(#2849)](https://github.com/PennyLaneAI/pennylane/pull/2849) From 1c6ec0e9d756b13a18dee4192e88a025b88c80c3 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 15:33:18 +0100 Subject: [PATCH 14/35] test (Observable): :test_tube: Remove test. --- tests/test_operation.py | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/tests/test_operation.py b/tests/test_operation.py index b7e50a1ddbe..6d988d01f70 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -1164,30 +1164,6 @@ def test_multiply_tensor_in_place(self): assert isinstance(t, Tensor) assert t.obs == [X, Y, Z, H] - def test_operation_multiply_invalid(self): - """Test that an exception is raised if an observable - is multiplied by an operation""" - X = qml.PauliX(0) - Y = qml.CNOT(wires=[0, 1]) - Z = qml.PauliZ(0) - - with pytest.raises( - ValueError, match="Can only perform tensor products between observables" - ): - X @ Y - - with pytest.raises( - ValueError, match="Can only perform tensor products between observables" - ): - T = X @ Z - T @ Y - - with pytest.raises( - ValueError, match="Can only perform tensor products between observables" - ): - T = X @ Z - Y @ T - def test_eigvals(self): """Test that the correct eigenvalues are returned for the Tensor""" X = qml.PauliX(0) From 5bbbc57f83af579ed7d7ab009a1180b5f538360b Mon Sep 17 00:00:00 2001 From: Albert Mitjans Date: Thu, 4 Aug 2022 16:47:10 +0200 Subject: [PATCH 15/35] Update doc/releases/changelog-dev.md Co-authored-by: Christina Lee --- doc/releases/changelog-dev.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index f8312c29a84..c4b83259396 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -363,7 +363,7 @@ [(#2891)](https://github.com/PennyLaneAI/pennylane/pull/2891) ```pycon - >>> prod_op = qml.PauliX(0) @ qml.PauliX(1) + >>> prod_op = qml.RX(1, wires=0) @ qml.RY(2, wires=0) >>> prod_op PauliX(wires=[0]) @ PauliZ(wires=[1]) >>> sprod_op = 6 * qml.RX(1, 0) From 0ab97db879d568a1e71762a974c6e6189fd5b3c9 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 15:50:55 +0100 Subject: [PATCH 16/35] fix (Operator): :bug: Use only one wire with Identity. --- pennylane/operation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/operation.py b/pennylane/operation.py index 7b74f002980..e01af87c006 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1213,7 +1213,7 @@ def __add__(self, other): return qml.ops.Sum( # pylint: disable=no-member self, qml.ops.SProd( # pylint: disable=no-member - scalar=other, base=qml.Identity(wires=self.wires) + scalar=other, base=qml.Identity(wires=self.wires[0]) ), ) if isinstance(other, Operator): From fd6e53e91209eb4579576d4f354f301870346017 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 16:17:45 +0100 Subject: [PATCH 17/35] test (Operator): :test_tube: Increase coverage. --- pennylane/operation.py | 4 ++-- tests/test_operation.py | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/pennylane/operation.py b/pennylane/operation.py index e01af87c006..036448330fa 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1226,7 +1226,7 @@ def __mul__(self, other): """The scalar multiplication between scalars and Operators.""" if isinstance(other, numbers.Number): return qml.ops.SProd(scalar=other, base=self) # pylint: disable=no-member - raise ValueError(f"Cannot multiply Operator and {type(other)}") + raise ValueError(f"Cannot multiply Operator and {type(other)}.") __rmul__ = __mul__ @@ -1234,7 +1234,7 @@ def __matmul__(self, other): """The product operation between Operator objects.""" if isinstance(other, Operator): return qml.ops.Prod(self, other) # pylint: disable=no-member - raise ValueError(f"Cannot multiply Operator and {type(other)}") + raise ValueError("Can only perform tensor products between observables.") def __sub__(self, other): """The substraction operation of Operator-Operator objects and Operator-scalar.""" diff --git a/tests/test_operation.py b/tests/test_operation.py index 6d988d01f70..d3a6bd38ca5 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -827,8 +827,13 @@ def test_mul_with_not_supported_object_raises_error(self): """Test that the __mul__ dunder method raises an error when using a non-supported object.""" with pytest.raises(ValueError, match="Cannot multiply Observable by"): _ = "dummy" * qml.PauliX(0) - with pytest.raises(ValueError, match="Cannot multiply Observable by"): - _ = qml.PauliX(0) * "dummy" + + def test_matmul_with_not_supported_object_raises_error(self): + """Test that the __matmul__ dunder method raises an error when using a non-supported object.""" + with pytest.raises( + ValueError, match="Can only perform tensor products between observables." + ): + _ = qml.PauliX(0) @ "dummy" class TestInverse: From 4d0e710820f2a05cba0fdb354a4cd83ff1b4dbf9 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 16:52:09 +0100 Subject: [PATCH 18/35] test (Operator): :test_tube: Increase coverage. --- tests/test_operation.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/test_operation.py b/tests/test_operation.py index d3a6bd38ca5..05ad681af23 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -1169,6 +1169,19 @@ def test_multiply_tensor_in_place(self): assert isinstance(t, Tensor) assert t.obs == [X, Y, Z, H] + def test_operation_multiply_invalid(self): + """Test that an exception is raised if an observable + is multiplied by an operation""" + X = qml.PauliX(0) + Y = qml.CNOT(wires=[0, 1]) + Z = qml.PauliZ(0) + + with pytest.raises( + ValueError, match="Can only perform tensor products between observables" + ): + T = X @ Z + T @ Y + def test_eigvals(self): """Test that the correct eigenvalues are returned for the Tensor""" X = qml.PauliX(0) From bd0f7b610a00d1147e1e8d31c67ab98fbf6f8f87 Mon Sep 17 00:00:00 2001 From: Albert Mitjans Date: Thu, 4 Aug 2022 18:09:37 +0200 Subject: [PATCH 19/35] Update pennylane/operation.py Co-authored-by: Jay Soni --- pennylane/operation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/operation.py b/pennylane/operation.py index 036448330fa..9c91713b15d 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1234,7 +1234,7 @@ def __matmul__(self, other): """The product operation between Operator objects.""" if isinstance(other, Operator): return qml.ops.Prod(self, other) # pylint: disable=no-member - raise ValueError("Can only perform tensor products between observables.") + raise ValueError("Can only perform tensor products between operators.") def __sub__(self, other): """The substraction operation of Operator-Operator objects and Operator-scalar.""" From c8a487a78fe96264dd8ae529bd7c1cbc3f8c7797 Mon Sep 17 00:00:00 2001 From: Albert Mitjans Date: Thu, 4 Aug 2022 18:09:53 +0200 Subject: [PATCH 20/35] Update pennylane/operation.py Co-authored-by: Jay Soni --- pennylane/operation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/operation.py b/pennylane/operation.py index 9c91713b15d..a9fa3eea3c0 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1652,7 +1652,7 @@ def __matmul__(self, other): try: return super().__matmul__(other=other) except ValueError as e: - raise ValueError("Can only perform tensor products between observables.") from e + raise ValueError("Can only perform tensor products between operators.") from e def _obs_data(self): r"""Extracts the data from a Observable or Tensor and serializes it in an order-independent fashion. From e92635a22cba0afa74382c380d322450bd30fcad Mon Sep 17 00:00:00 2001 From: Albert Mitjans Date: Thu, 4 Aug 2022 18:14:32 +0200 Subject: [PATCH 21/35] Update tests/test_operation.py Co-authored-by: Jay Soni --- tests/test_operation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_operation.py b/tests/test_operation.py index 05ad681af23..167a972934e 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -814,7 +814,7 @@ def test_mul_with_scalar(self): assert np.allclose(sprod_op.matrix(), final_op.matrix(), rtol=0) def test_mul_with_operator(self): - """Test the __mul__ dunder method with an operator.""" + """Test the __matmul__ dunder method with an operator.""" prod_op = qml.PauliX(0) @ qml.RX(1, 0) final_op = qml.ops.Prod(qml.PauliX(0), qml.RX(1, 0)) assert isinstance(prod_op, qml.ops.Prod) From 1c900d6234c33299b118e8fed69286191fc98fd9 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 17:25:25 +0100 Subject: [PATCH 22/35] test (Operator): :test_tube: Fix test. --- tests/test_operation.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test_operation.py b/tests/test_operation.py index 167a972934e..67c22b788de 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -830,9 +830,7 @@ def test_mul_with_not_supported_object_raises_error(self): def test_matmul_with_not_supported_object_raises_error(self): """Test that the __matmul__ dunder method raises an error when using a non-supported object.""" - with pytest.raises( - ValueError, match="Can only perform tensor products between observables." - ): + with pytest.raises(ValueError, match="Can only perform tensor products between operators."): _ = qml.PauliX(0) @ "dummy" From e99d1b364a7af94d988f7164220968b726920eac Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 22:05:19 +0100 Subject: [PATCH 23/35] test (Operator): :test_tube: Support add for multiple wires. --- pennylane/operation.py | 10 +++++++--- tests/test_operation.py | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/pennylane/operation.py b/pennylane/operation.py index a9fa3eea3c0..89893b7cf5f 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1210,11 +1210,15 @@ def __add__(self, other): if isinstance(other, numbers.Number): if other == 0: return self + wires = self.wires.tolist() + id_op = ( + qml.ops.Prod(*(qml.Identity(w) for w in wires)) # pylint: disable=no-member + if len(wires) > 1 + else qml.Identity(wires[0]) + ) return qml.ops.Sum( # pylint: disable=no-member self, - qml.ops.SProd( # pylint: disable=no-member - scalar=other, base=qml.Identity(wires=self.wires[0]) - ), + qml.ops.SProd(scalar=other, base=id_op), # pylint: disable=no-member ) if isinstance(other, Operator): return qml.ops.Sum(self, other) # pylint: disable=no-member diff --git a/tests/test_operation.py b/tests/test_operation.py index 67c22b788de..9c64979d0e3 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -789,6 +789,21 @@ def test_sum_with_scalar(self): assert s1.data == s2.data assert np.allclose(a=sum_op.matrix(), b=final_op.matrix(), rtol=0) + def test_sum_multi_wire_operator_with_scalar(self): + """Test the __sum__ dunder method with a multi-wire operator and a scalar value.""" + sum_op = 5 + qml.CNOT(wires=[0, 1]) + final_op = qml.ops.Sum( + qml.CNOT(wires=[0, 1]), + qml.ops.s_prod(5, qml.ops.Prod(qml.Identity(0), qml.Identity(1))), + ) + # TODO: Use qml.equal when fixed. + assert isinstance(sum_op, qml.ops.Sum) + for s1, s2 in zip(sum_op.summands, final_op.summands): + assert s1.name == s2.name + assert s1.wires == s2.wires + assert s1.data == s2.data + assert np.allclose(a=sum_op.matrix(), b=final_op.matrix(), rtol=0) + def test_dunder_methods(self): """Test the __sub__, __rsub__ and __neg__ dunder methods.""" sum_op = qml.PauliX(0) - 5 From 7eb39149bb480a5e1d2667c41be982267024e0a4 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 22:51:12 +0100 Subject: [PATCH 24/35] test (Operator): :test_tube: Increase coverage. --- tests/test_operation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_operation.py b/tests/test_operation.py index 9c64979d0e3..ab3044cff43 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -830,8 +830,8 @@ def test_mul_with_scalar(self): def test_mul_with_operator(self): """Test the __matmul__ dunder method with an operator.""" - prod_op = qml.PauliX(0) @ qml.RX(1, 0) - final_op = qml.ops.Prod(qml.PauliX(0), qml.RX(1, 0)) + prod_op = qml.RX(1, 0) @ qml.PauliX(0) + final_op = qml.ops.Prod(qml.RX(1, 0), qml.PauliX(0)) assert isinstance(prod_op, qml.ops.Prod) assert prod_op.name == final_op.name assert prod_op.wires == final_op.wires From 4f85e5da50f664eec68aaafe87dbdc595fe8a540 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 22:56:20 +0100 Subject: [PATCH 25/35] feat (s_prod): :sparkles: Add to init. --- pennylane/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/__init__.py b/pennylane/__init__.py index e4a27f9f7f7..1c5ad649389 100644 --- a/pennylane/__init__.py +++ b/pennylane/__init__.py @@ -58,7 +58,7 @@ mutual_info, ) from pennylane.ops import * -from pennylane.ops import adjoint, ctrl, op_sum, prod +from pennylane.ops import adjoint, ctrl, op_sum, prod, s_prod from pennylane.templates import broadcast, layer from pennylane.templates.embeddings import * from pennylane.templates.layers import * From a66f6edce7072c8a37b4c2d7ee777bf1e2440fe2 Mon Sep 17 00:00:00 2001 From: Albert Mitjans Date: Thu, 4 Aug 2022 23:56:35 +0200 Subject: [PATCH 26/35] Update pennylane/operation.py Co-authored-by: Christina Lee --- pennylane/operation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/operation.py b/pennylane/operation.py index 89893b7cf5f..c2f4c12f4ba 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1229,7 +1229,7 @@ def __add__(self, other): def __mul__(self, other): """The scalar multiplication between scalars and Operators.""" if isinstance(other, numbers.Number): - return qml.ops.SProd(scalar=other, base=self) # pylint: disable=no-member + return qml.s_prod(scalar=other, base=self) raise ValueError(f"Cannot multiply Operator and {type(other)}.") __rmul__ = __mul__ From b4f6395bc8133afa07c0b377f4813a3b0435eb2f Mon Sep 17 00:00:00 2001 From: Albert Mitjans Date: Thu, 4 Aug 2022 23:56:40 +0200 Subject: [PATCH 27/35] Update pennylane/operation.py Co-authored-by: Christina Lee --- pennylane/operation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/operation.py b/pennylane/operation.py index c2f4c12f4ba..e5f70b04e2e 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1237,7 +1237,7 @@ def __mul__(self, other): def __matmul__(self, other): """The product operation between Operator objects.""" if isinstance(other, Operator): - return qml.ops.Prod(self, other) # pylint: disable=no-member + return qml.prod(self, other) raise ValueError("Can only perform tensor products between operators.") def __sub__(self, other): From b6bbf5a5f1d58421f4f0ac6a26eb749da51f5080 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 23:12:29 +0100 Subject: [PATCH 28/35] fix: :bug: Fix small bug. --- pennylane/operation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/operation.py b/pennylane/operation.py index e5f70b04e2e..32b6104ab23 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1229,7 +1229,7 @@ def __add__(self, other): def __mul__(self, other): """The scalar multiplication between scalars and Operators.""" if isinstance(other, numbers.Number): - return qml.s_prod(scalar=other, base=self) + return qml.s_prod(scalar=other, operator=self) raise ValueError(f"Cannot multiply Operator and {type(other)}.") __rmul__ = __mul__ From fec905dd78632433eb1f87e1f61abedc111c734c Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Thu, 4 Aug 2022 23:31:05 +0100 Subject: [PATCH 29/35] test (Operator): :test_tube: Add test. --- tests/test_operation.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/test_operation.py b/tests/test_operation.py index ab3044cff43..39e35cd54cf 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -777,9 +777,21 @@ class DummyOp(qml.operation.Operation): with pytest.raises(ValueError, match="Cannot raise an Operator"): _ = DummyOp(wires=[0]) ** DummyOp(wires=[0]) + def test_sum_with_operator(self): + """Test the __sum__ dunder method with two operators.""" + sum_op = qml.PauliX(0) + qml.RX(1, 0) + final_op = qml.op_sum(qml.PauliX(0), qml.RX(1, 0)) + # TODO: Use qml.equal when fixed. + assert isinstance(sum_op, qml.ops.Sum) + for s1, s2 in zip(sum_op.summands, final_op.summands): + assert s1.name == s2.name + assert s1.wires == s2.wires + assert s1.data == s2.data + assert np.allclose(a=sum_op.matrix(), b=final_op.matrix(), rtol=0) + def test_sum_with_scalar(self): """Test the __sum__ dunder method with a scalar value.""" - sum_op = 5 + qml.PauliX(0) + sum_op = 5 + qml.PauliX(0) + 0 final_op = qml.ops.Sum(qml.PauliX(0), qml.ops.s_prod(5, qml.Identity(0))) # TODO: Use qml.equal when fixed. assert isinstance(sum_op, qml.ops.Sum) From ab5ade48d6c78d1d540f39b2bcb91f3f46c7d070 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Fri, 5 Aug 2022 09:52:41 +0100 Subject: [PATCH 30/35] test (Operator): :test_tube: Add test. --- tests/test_operation.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/test_operation.py b/tests/test_operation.py index 39e35cd54cf..a8337b5a086 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -850,6 +850,14 @@ def test_mul_with_operator(self): assert prod_op.data == final_op.data assert np.allclose(prod_op.matrix(), final_op.matrix(), rtol=0) + def test_multiply_operator_with_observable_valid(self): + """Test that now it is valid to multiply an operator with an observable.""" + PX = qml.PauliX(0) + CNOT = qml.CNOT(wires=[0, 1]) + PZ = qml.PauliZ(0) + PX @ CNOT + CNOT @ (PX @ PZ) + def test_mul_with_not_supported_object_raises_error(self): """Test that the __mul__ dunder method raises an error when using a non-supported object.""" with pytest.raises(ValueError, match="Cannot multiply Observable by"): From 84bc3351e56c90d57083922ac9dc16c813ae7f89 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Fri, 5 Aug 2022 11:29:51 +0100 Subject: [PATCH 31/35] test (Operator): :test_tube: Add test. --- tests/test_operation.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test_operation.py b/tests/test_operation.py index a8337b5a086..a447e005322 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -1215,6 +1215,11 @@ def test_operation_multiply_invalid(self): T = X @ Z T @ Y + with pytest.raises( + ValueError, match="Can only perform tensor products between observables" + ): + _ = 4 @ X + def test_eigvals(self): """Test that the correct eigenvalues are returned for the Tensor""" X = qml.PauliX(0) From 39bb8605329c178b95ccf6b0bba82c88f65e217a Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Fri, 5 Aug 2022 12:17:09 +0100 Subject: [PATCH 32/35] test (Operator): :test_tube: Add test. --- tests/test_operation.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/tests/test_operation.py b/tests/test_operation.py index a447e005322..c4fb75855cc 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -816,7 +816,7 @@ def test_sum_multi_wire_operator_with_scalar(self): assert s1.data == s2.data assert np.allclose(a=sum_op.matrix(), b=final_op.matrix(), rtol=0) - def test_dunder_methods(self): + def test_sub_rsub_and_neg_dunder_methods(self): """Test the __sub__, __rsub__ and __neg__ dunder methods.""" sum_op = qml.PauliX(0) - 5 sum_op_2 = -(5 - qml.PauliX(0)) @@ -850,14 +850,6 @@ def test_mul_with_operator(self): assert prod_op.data == final_op.data assert np.allclose(prod_op.matrix(), final_op.matrix(), rtol=0) - def test_multiply_operator_with_observable_valid(self): - """Test that now it is valid to multiply an operator with an observable.""" - PX = qml.PauliX(0) - CNOT = qml.CNOT(wires=[0, 1]) - PZ = qml.PauliZ(0) - PX @ CNOT - CNOT @ (PX @ PZ) - def test_mul_with_not_supported_object_raises_error(self): """Test that the __mul__ dunder method raises an error when using a non-supported object.""" with pytest.raises(ValueError, match="Cannot multiply Observable by"): @@ -1218,7 +1210,8 @@ def test_operation_multiply_invalid(self): with pytest.raises( ValueError, match="Can only perform tensor products between observables" ): - _ = 4 @ X + T = X @ Z + 4 @ T def test_eigvals(self): """Test that the correct eigenvalues are returned for the Tensor""" From 624e23eb6718c45128fc90d545340f3c1070d341 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Fri, 5 Aug 2022 12:34:17 +0100 Subject: [PATCH 33/35] refactor (Operator): :recycle: Use wrappers. --- pennylane/operation.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/pennylane/operation.py b/pennylane/operation.py index 32b6104ab23..ad5138e2dae 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1212,16 +1212,13 @@ def __add__(self, other): return self wires = self.wires.tolist() id_op = ( - qml.ops.Prod(*(qml.Identity(w) for w in wires)) # pylint: disable=no-member + qml.prod(*(qml.Identity(w) for w in wires)) if len(wires) > 1 else qml.Identity(wires[0]) ) - return qml.ops.Sum( # pylint: disable=no-member - self, - qml.ops.SProd(scalar=other, base=id_op), # pylint: disable=no-member - ) + return qml.op_sum(self, qml.s_prod(scalar=other, operator=id_op)) if isinstance(other, Operator): - return qml.ops.Sum(self, other) # pylint: disable=no-member + return qml.op_sum(self, other) raise ValueError(f"Cannot add Operator and {type(other)}") __radd__ = __add__ @@ -1252,7 +1249,7 @@ def __rsub__(self, other): def __neg__(self): """The negation operation of an Operator object.""" - return qml.ops.SProd(scalar=-1, base=self) # pylint: disable=no-member + return qml.s_prod(scalar=-1, operator=self) def __pow__(self, other): r"""The power operation of an Operator object.""" From bfe569dad98d51d8ea3408c0806b1907e1ffe3d5 Mon Sep 17 00:00:00 2001 From: AlbertMitjans Date: Fri, 5 Aug 2022 12:36:44 +0100 Subject: [PATCH 34/35] refactor (Operator): :recycle: Use wrappers. --- tests/test_operation.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_operation.py b/tests/test_operation.py index c4fb75855cc..2ea0d642e7d 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -792,7 +792,7 @@ def test_sum_with_operator(self): def test_sum_with_scalar(self): """Test the __sum__ dunder method with a scalar value.""" sum_op = 5 + qml.PauliX(0) + 0 - final_op = qml.ops.Sum(qml.PauliX(0), qml.ops.s_prod(5, qml.Identity(0))) + final_op = qml.op_sum(qml.PauliX(0), qml.s_prod(5, qml.Identity(0))) # TODO: Use qml.equal when fixed. assert isinstance(sum_op, qml.ops.Sum) for s1, s2 in zip(sum_op.summands, final_op.summands): @@ -804,9 +804,9 @@ def test_sum_with_scalar(self): def test_sum_multi_wire_operator_with_scalar(self): """Test the __sum__ dunder method with a multi-wire operator and a scalar value.""" sum_op = 5 + qml.CNOT(wires=[0, 1]) - final_op = qml.ops.Sum( + final_op = qml.op_sum( qml.CNOT(wires=[0, 1]), - qml.ops.s_prod(5, qml.ops.Prod(qml.Identity(0), qml.Identity(1))), + qml.s_prod(5, qml.prod(qml.Identity(0), qml.Identity(1))), ) # TODO: Use qml.equal when fixed. assert isinstance(sum_op, qml.ops.Sum) @@ -829,7 +829,7 @@ def test_mul_with_scalar(self): """Test the __mul__ dunder method with a scalar value.""" sprod_op = 4 * qml.RX(1, 0) sprod_op2 = qml.RX(1, 0) * 4 - final_op = qml.ops.SProd(scalar=4, base=qml.RX(1, 0)) + final_op = qml.s_prod(scalar=4, operator=qml.RX(1, 0)) assert isinstance(sprod_op, qml.ops.SProd) assert sprod_op.name == sprod_op2.name assert sprod_op.wires == sprod_op2.wires @@ -843,7 +843,7 @@ def test_mul_with_scalar(self): def test_mul_with_operator(self): """Test the __matmul__ dunder method with an operator.""" prod_op = qml.RX(1, 0) @ qml.PauliX(0) - final_op = qml.ops.Prod(qml.RX(1, 0), qml.PauliX(0)) + final_op = qml.prod(qml.RX(1, 0), qml.PauliX(0)) assert isinstance(prod_op, qml.ops.Prod) assert prod_op.name == final_op.name assert prod_op.wires == final_op.wires From 4d6f3cf4b53d2ac75c47929b4bbc89383419bdd5 Mon Sep 17 00:00:00 2001 From: Albert Mitjans Date: Fri, 5 Aug 2022 15:39:51 +0200 Subject: [PATCH 35/35] Update pennylane/operation.py Co-authored-by: Christina Lee --- pennylane/operation.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pennylane/operation.py b/pennylane/operation.py index ad5138e2dae..9abdc9a03fa 100644 --- a/pennylane/operation.py +++ b/pennylane/operation.py @@ -1210,11 +1210,10 @@ def __add__(self, other): if isinstance(other, numbers.Number): if other == 0: return self - wires = self.wires.tolist() id_op = ( - qml.prod(*(qml.Identity(w) for w in wires)) - if len(wires) > 1 - else qml.Identity(wires[0]) + qml.prod(*(qml.Identity(w) for w in self.wires)) + if len(self.wires) > 1 + else qml.Identity(self.wires[0]) ) return qml.op_sum(self, qml.s_prod(scalar=other, operator=id_op)) if isinstance(other, Operator):