Repository: PennyLaneAI/pennylane
Pull request #2172 (2022-02-05 00:19:45)

fixed bug when trying to insert around an observable
Bug when trying to insert around an `operation` which also inherits from other classes. 

Eg: 
```python 
    with qml.tape.QuantumTape() as tape:
        qml.PauliX(wires=0)
        qml.expval(qml.PauliX(wires=1))
    
    updated_tape = qml.transforms.insert(qml.Hadamard, (), position=qml.PauliX, before=True)(tape)
```

This would raise a `ValueError` because `qml.PauliX.__base__ != Operation`. But this is because `qml.PauliX` inherits from both `Operation` and `Observable`. 

## Solution: 

Updated logic to check if `Operation is in qml.Paulix.__bases__` 

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/2172?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
> :exclamation: No coverage uploaded for pull request base (`v0.21.0-rc0@2a419f4`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#section-missing-base-commit).
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2172/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/2172?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)

```diff
@@              Coverage Diff               @@
##             v0.21.0-rc0    #2172   +/-   ##
==============================================
  Coverage               ?   96.38%           
==============================================
  Files                  ?      230           
  Lines                  ?    17665           
  Branches               ?        0           
==============================================
  Hits                   ?    17026           
  Misses                 ?      639           
  Partials               ?        0           
```



------

[Continue to review full report at Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2172?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/2172?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Last update [2a419f4...50719a1](https://codecov.io/gh/PennyLaneAI/pennylane/pull/2172?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).


Patch:
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index 19164addb..858c80953 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -594,6 +594,10 @@
   operator.
   [(#2133)](https://github.com/PennyLaneAI/pennylane/pull/2133)
 
+* Fixed a bug in `insert()` which prevented operations that inherited
+  from multiple classes to be inserted. 
+  [(#2172)](https://github.com/PennyLaneAI/pennylane/pull/2172)
+
 * <h3>Documentation</h3>
 
 * Fixes an error in the signs of equations in the `DoubleExcitation` page.
diff --git a/pennylane/transforms/insert_ops.py b/pennylane/transforms/insert_ops.py
index 7ec72f172..b207ff8d7 100644
--- a/pennylane/transforms/insert_ops.py
+++ b/pennylane/transforms/insert_ops.py
@@ -35,13 +35,13 @@ def _check_position(position):
         req_ops = position.copy()
         for operation in req_ops:
             try:
-                if operation.__base__ != Operation:
+                if Operation not in operation.__bases__:
                     not_op = True
             except AttributeError:
                 not_op = True
     elif not isinstance(position, list):
         try:
-            if position.__base__ == Operation:
+            if Operation in position.__bases__:
                 req_ops = [position]
             else:
                 not_op = True


Test patch:
diff --git a/tests/transforms/test_insert_ops.py b/tests/transforms/test_insert_ops.py
index ee18a67cb..d2cd247c5 100644
--- a/tests/transforms/test_insert_ops.py
+++ b/tests/transforms/test_insert_ops.py
@@ -46,6 +46,15 @@ class TestInsert:
         qml.RX(0.6, wires=1)
         qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))
 
+    with QuantumTape() as custom_tape:
+        qml.RX(0.9, wires=0)
+        qml.RY(0.4, wires=1)
+        qml.CNOT(wires=[0, 1])
+        qml.RY(0.5, wires=0)
+        qml.PauliZ(wires=1)
+        qml.Identity(wires=2)
+        qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))
+
     def test_multiwire_op(self):
         """Tests if a ValueError is raised when multiqubit operations are requested"""
         with pytest.raises(ValueError, match="Only single-qubit operations can be inserted into"):
@@ -140,18 +149,30 @@ class TestInsert:
         assert tape.observables[0].wires.tolist() == [0, 1]
         assert tape.measurements[0].return_type is Expectation
 
-    def test_operation_as_position(self):
+    op_lst = [qml.RX, qml.PauliZ, qml.Identity]
+
+    @pytest.mark.parametrize("op", op_lst)
+    def test_operation_as_position(self, op):
         """Test if expected tape is returned when an operation is passed in position"""
-        tape = insert(qml.PhaseDamping, 0.4, position=qml.RX, before=True)(self.tape)
+        tape = insert(qml.PhaseDamping, 0.4, position=op, before=True)(self.custom_tape)
 
         with QuantumTape() as tape_exp:
-            qml.PhaseDamping(0.4, wires=0)
+            if op == qml.RX:
+                qml.PhaseDamping(0.4, wires=0)
             qml.RX(0.9, wires=0)
+
             qml.RY(0.4, wires=1)
             qml.CNOT(wires=[0, 1])
             qml.RY(0.5, wires=0)
-            qml.PhaseDamping(0.4, wires=1)
-            qml.RX(0.6, wires=1)
+
+            if op == qml.PauliZ:
+                qml.PhaseDamping(0.4, wires=1)
+            qml.PauliZ(wires=1)
+
+            if op == qml.Identity:
+                qml.PhaseDamping(0.4, wires=2)
+            qml.Identity(wires=2)
+
             qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))
 
         assert all(o1.name == o2.name for o1, o2 in zip(tape.operations, tape_exp.operations))