Repository: PennyLaneAI/pennylane
Pull request #1273 (2021-05-04 21:44:02)

Prevent Hamiltonians that share wires from being multiplied together
Raises a `ValueError` if Hamiltonians sharing wires are multiplied together:

```python
h1 = qml.Hamiltonian([1, 1], [qml.PauliZ(0), qml.PauliZ(1)])
h1 @ h1
```
This will raise a `ValueError`.

Fixes https://github.com/PennyLaneAI/pennylane/issues/1272 although this is just to help prevent users getting caught-out, we still need a better solution for manipulation of Hamiltonians.

github-actions[bot]: Hello. You may have forgotten to update the changelog!
Please edit [.github/CHANGELOG.md](/PennyLaneAI/pennylane/blob/master/.github/CHANGELOG.md) with:
* A one-to-two sentence description of the change. You may include a small working example for new features.
* A link back to this PR.
* Your name (or GitHub username) in the contributors section.
codecov[bot]: # [Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1273?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
> Merging [#1273](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1273?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (28301e8) into [master](https://codecov.io/gh/PennyLaneAI/pennylane/commit/8fe31ad619222e2992130c5d036571f6ef7ab51c?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (8fe31ad) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1273/graphs/tree.svg?width=650&height=150&src=pr&token=9S3YzlUgGk&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1273?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)

```diff
@@           Coverage Diff           @@
##           master    #1273   +/-   ##
=======================================
  Coverage   98.12%   98.12%           
=======================================
  Files         146      146           
  Lines       11071    11075    +4     
=======================================
+ Hits        10863    10867    +4     
  Misses        208      208           
```


| [Impacted Files](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1273?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) | Coverage Δ | |
|---|---|---|
| [pennylane/vqe/vqe.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1273/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3ZxZS92cWUucHk=) | `92.97% <100.00%> (+0.15%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1273?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1273?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Last update [8fe31ad...28301e8](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1273?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).

josh146: > Looks good! 👍 In the long term, maybe `@` can call grouping.pauli_mult for cases like this (though I think there would be some things to iron out in terms of wire maps -- perhaps @josh146 can speak further to this, he pointed it out while reviewing #1181).

Alternatively, is there anything stopping us from having `__matmul__` call `grouping.pauli_mult` in the short term? 🙂 It might solve a lot of open issues we have on operator multiplication
anthayes92: Nice short term solution! A long term fix for this would render [1213](https://github.com/PennyLaneAI/pennylane/pull/1213) obselete. 

Patch:
diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md
index 3615a5139..1cf4343c2 100644
--- a/.github/CHANGELOG.md
+++ b/.github/CHANGELOG.md
@@ -128,6 +128,9 @@ random_mat2 = rng.standard_normal(3, requires_grad=False)
 
 <h3>Bug fixes</h3>
 
+* Prevent Hamiltonians that share wires from being multiplied together.
+  [(#1273)](https://github.com/PennyLaneAI/pennylane/pull/1273)
+
 <h3>Documentation</h3>
 
 * Remove unsupported `None` option from the `qml.QNode` docstrings.
diff --git a/pennylane/vqe/vqe.py b/pennylane/vqe/vqe.py
index 66e479b3b..695ce354d 100644
--- a/pennylane/vqe/vqe.py
+++ b/pennylane/vqe/vqe.py
@@ -23,6 +23,7 @@ import warnings
 import pennylane as qml
 from pennylane import numpy as np
 from pennylane.operation import Observable, Tensor
+from pennylane.wires import Wires
 
 OBS_MAP = {"PauliX": "X", "PauliY": "Y", "PauliZ": "Z", "Hadamard": "H", "Identity": "I"}
 
@@ -286,6 +287,13 @@ class Hamiltonian:
         terms1 = self.ops.copy()
 
         if isinstance(H, Hamiltonian):
+            shared_wires = Wires.shared_wires([self.wires, H.wires])
+            if len(shared_wires) > 0:
+                raise ValueError(
+                    "Hamiltonians can only be multiplied together if they act on "
+                    "different sets of wires"
+                )
+
             coeffs2 = H.coeffs
             terms2 = H.ops
 


Test patch:
diff --git a/tests/test_vqe.py b/tests/test_vqe.py
index dd395f2f2..6999d02f2 100644
--- a/tests/test_vqe.py
+++ b/tests/test_vqe.py
@@ -696,6 +696,14 @@ class TestHamiltonian:
         """Tests that Hamiltonians are tensored correctly"""
         assert H.compare(H1 @ H2)
 
+    def test_hamiltonian_same_wires(self):
+        """Test if a ValueError is raised when multiplication between Hamiltonians acting on the
+        same wires is attempted"""
+        h1 = qml.Hamiltonian([1, 1], [qml.PauliZ(0), qml.PauliZ(1)])
+
+        with pytest.raises(ValueError, match="Hamiltonians can only be multiplied together if"):
+            h1 @ h1
+
     @pytest.mark.parametrize(("H1", "H2", "H"), add_hamiltonians)
     def test_hamiltonian_iadd(self, H1, H2, H):
         """Tests that Hamiltonians are added inline correctly"""