Repository: PennyLaneAI/pennylane
Pull request #3459 (2022-12-02 15:44:58)

Warning for tensor
**Context:**
PennyLane allows users to create `Tensor` objects with overlapping wires, and in certain contexts treating this as a dot product is supported (for example, `Tensor(qml.PauliX(0), qml.PauliY(0)).matrix()`). However, some functions in PennyLane assume that a `Tensor` object is a mathematical tensor, leading to undefined behaviour if this isn't the case. This creates a lack of clarity regarding whether or not users should expect `@` to allow correctly defining a dot product.

**Description of the Change:**
Add a UserWarning when first creating a Tensor object with overlapping wires, informing the user that this is not supported by all functions in PennyLane and may lead to undefined behaviour.

**Benefits:**
Clarity regarding correct use of the `Tensor` class, and what to expect if trying to use the `@` symbol to define a dot product.

**Related GitHub Issues:**
#715, #1107


github-actions[bot]: Hello. You may have forgotten to update the changelog!
Please edit [`doc/releases/changelog-dev.md`](/PennyLaneAI/pennylane/blob/master/doc/releases/changelog-dev.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/3459?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
> Merging [#3459](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3459?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (5c21c2f) into [master](https://codecov.io/gh/PennyLaneAI/pennylane/commit/60cd8548fb36e6e726eb15169e66d8a7d294386e?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (60cd854) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

```diff
@@           Coverage Diff            @@
##           master    #3459    +/-   ##
========================================
  Coverage   99.68%   99.68%            
========================================
  Files         299      307     +8     
  Lines       26720    26985   +265     
========================================
+ Hits        26635    26900   +265     
  Misses         85       85            
```


| [Impacted Files](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3459?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) | Coverage Δ | |
|---|---|---|
| [pennylane/operation.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3459/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wZXJhdGlvbi5weQ==) | `97.03% <100.00%> (+0.02%)` | :arrow_up: |
| [pennylane/pauli/utils.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3459/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3BhdWxpL3V0aWxzLnB5) | `100.00% <0.00%> (ø)` | |
| [pennylane/pauli/\_\_init\_\_.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3459/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3BhdWxpL19faW5pdF9fLnB5) | `100.00% <0.00%> (ø)` | |
| [pennylane/ops/op\_math/exp.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3459/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9vcF9tYXRoL2V4cC5weQ==) | `100.00% <0.00%> (ø)` | |
| [pennylane/measurements/var.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3459/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL21lYXN1cmVtZW50cy92YXIucHk=) | `100.00% <0.00%> (ø)` | |
| [pennylane/qinfo/transforms.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3459/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3FpbmZvL3RyYW5zZm9ybXMucHk=) | `100.00% <0.00%> (ø)` | |
| [pennylane/measurements/probs.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3459/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL21lYXN1cmVtZW50cy9wcm9icy5weQ==) | `100.00% <0.00%> (ø)` | |
| [pennylane/measurements/state.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3459/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL21lYXN1cmVtZW50cy9zdGF0ZS5weQ==) | `100.00% <0.00%> (ø)` | |
| [pennylane/ops/qubit/\_\_init\_\_.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3459/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9xdWJpdC9fX2luaXRfXy5weQ==) | `100.00% <0.00%> (ø)` | |
| [pennylane/shadows/transforms.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3459/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3NoYWRvd3MvdHJhbnNmb3Jtcy5weQ==) | `100.00% <0.00%> (ø)` | |
| ... and [24 more](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3459/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)


Patch:
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index 4f99ff8da..974c22824 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -261,6 +261,10 @@
   Replaces `qml.transforms.make_tape` with `make_qscript`.
   [(#3429)](https://github.com/PennyLaneAI/pennylane/pull/3429)
 
+* Add a UserWarning when creating a `Tensor` object with overlapping wires, 
+  informing that this can in some cases lead to undefined behaviour.
+  [(#3459)](https://github.com/PennyLaneAI/pennylane/pull/3459)
+
 * Extended the `qml.equal` function to `Controlled` and `ControlledOp` objects.
   [(#3463)](https://github.com/PennyLaneAI/pennylane/pull/3463)
 
diff --git a/pennylane/operation.py b/pennylane/operation.py
index b422d7dec..acdcf7b07 100644
--- a/pennylane/operation.py
+++ b/pennylane/operation.py
@@ -1670,6 +1670,14 @@ class Tensor(Observable):
     tensor = True
 
     def __init__(self, *args):  # pylint: disable=super-init-not-called
+
+        wires = [op.wires for op in args]
+        if len(wires) != len(set(wires)):
+            warnings.warn(
+                "Tensor object acts on overlapping wires; in some PennyLane functions this will lead to undefined behaviour",
+                UserWarning,
+            )
+
         self._eigvals_cache = None
         self.obs: List[Observable] = []
         self._args = args
@@ -1826,6 +1834,13 @@ class Tensor(Observable):
         else:
             raise ValueError("Can only perform tensor products between observables.")
 
+        wires = [op.wires for op in self.obs]
+        if len(wires) != len(set(wires)):
+            warnings.warn(
+                "Tensor object acts on overlapping wires; in some PennyLane functions this will lead to undefined behaviour",
+                UserWarning,
+            )
+
         if QueuingManager.recording() and self not in QueuingManager.active_context():
             QueuingManager.append(self)
 


Test patch:
diff --git a/tests/test_operation.py b/tests/test_operation.py
index 1dea20640..e28ad6854 100644
--- a/tests/test_operation.py
+++ b/tests/test_operation.py
@@ -1144,6 +1144,18 @@ class TestTensor:
         ):
             Tensor(T, qml.CNOT(wires=[0, 1]))
 
+    def test_warning_for_overlapping_wires(self):
+        """Test that creating a Tensor with overlapping wires raises a warning"""
+        X = qml.PauliX(0)
+        Y = qml.PauliY(0)
+        op = qml.PauliX(0) @ qml.PauliY(1)
+
+        with pytest.warns(UserWarning, match="Tensor object acts on overlapping wires"):
+            Tensor(X, Y)
+
+        with pytest.warns(UserWarning, match="Tensor object acts on overlapping wires"):
+            op @ qml.PauliZ(1)
+
     def test_queuing_defined_outside(self):
         """Test the queuing of a Tensor object."""