Repository: PennyLaneAI/pennylane

Issue:
avoid redefining a build-in type
This pull request fixes a small function that names a variable `list`, thus overriding python's inbuilt type.


Discussion:

Resolving patch:
diff --git a/pennylane/tape/operation.py b/pennylane/tape/operation.py
--- a/pennylane/tape/operation.py
+++ b/pennylane/tape/operation.py
@@ -72,6 +72,9 @@ def operation_expand(self):
         # original operation has no trainable parameters
         tape.trainable_params = {}
 
+    if self.inverse:
+        tape.inv()
+
     return tape
 
 
diff --git a/pennylane/tape/qnode.py b/pennylane/tape/qnode.py
--- a/pennylane/tape/qnode.py
+++ b/pennylane/tape/qnode.py
@@ -395,17 +395,18 @@ def construct(self, args, kwargs):
         # provide the jacobian options
         self.qtape.jacobian_options = self.diff_options
 
-        stop_at = self.device.operations
-
         # pylint: disable=protected-access
         obs_on_same_wire = len(self.qtape._obs_sharing_wires) > 0
-        ops_not_supported = not {op.name for op in self.qtape.operations}.issubset(stop_at)
+        ops_not_supported = any(
+            not self.device.supports_operation(op.name) for op in self.qtape.operations
+        )
 
         # expand out the tape, if any operations are not supported on the device or multiple
         # observables are measured on the same wire
         if ops_not_supported or obs_on_same_wire:
             self.qtape = self.qtape.expand(
-                depth=self.max_expansion, stop_at=lambda obj: obj.name in stop_at
+                depth=self.max_expansion,
+                stop_at=lambda obj: self.device.supports_operation(obj.name),
             )
 
     def __call__(self, *args, **kwargs):


Test patch:
diff --git a/tests/devices/test_default_qubit.py b/tests/devices/test_default_qubit.py
--- a/tests/devices/test_default_qubit.py
+++ b/tests/devices/test_default_qubit.py
@@ -1880,3 +1880,77 @@ def test_partial_subsystem(self, mocker):
 
         assert np.all(res == state)
         spy.assert_called()
+
+
+@pytest.mark.usefixtures("tape_mode")
+class TestInverseDecomposition:
+    """Integration tests for decompositions of inverse gates"""
+
+    def test_inverse_S(self, tol):
+        """Test that applying the inverse of the S gate
+        works without decomposition"""
+
+        dev = qml.device('default.qubit', wires=1)
+
+        @qml.qnode(dev)
+        def test_s():
+            qml.Hadamard(wires=0)
+            qml.S(wires=0)
+            return qml.probs(wires=0)
+
+        test_s()
+        operations = test_s.qtape.operations if qml.tape_mode_active() else test_s.ops
+        assert "S" in [i.name for i in operations]
+
+        expected = np.array([1., 1.j]) / np.sqrt(2)
+        assert np.allclose(dev.state, expected, atol=tol, rtol=0)
+
+        @qml.qnode(dev)
+        def test_s_inverse():
+            qml.Hadamard(wires=0)
+            qml.S(wires=0).inv()
+            return qml.probs(wires=0)
+
+        test_s_inverse()
+        operations = test_s_inverse.qtape.operations if qml.tape_mode_active() else test_s_inverse.ops
+        assert "S.inv" in [i.name for i in operations]
+
+        expected = np.array([1., -1.j]) / np.sqrt(2)
+        assert np.allclose(dev.state, expected, atol=tol, rtol=0)
+
+    def test_inverse_S_decomposition(self, tol, monkeypatch):
+        """Test that applying the inverse of the S gate
+        works when the inverse S gate is decomposed"""
+        dev = qml.device('default.qubit', wires=1)
+
+        patched_operations = dev.operations.copy()
+        patched_operations.remove("S")
+        monkeypatch.setattr(dev, "operations", patched_operations)
+
+        @qml.qnode(dev)
+        def test_s():
+            qml.Hadamard(wires=0)
+            qml.S(wires=0)
+            return qml.probs(wires=0)
+
+        test_s()
+        operations = test_s.qtape.operations if qml.tape_mode_active() else test_s.ops
+        assert "S" not in [i.name for i in operations]
+        assert "PhaseShift" in [i.name for i in operations]
+
+        expected = np.array([1., 1.j]) / np.sqrt(2)
+        assert np.allclose(dev.state, expected, atol=tol, rtol=0)
+
+        @qml.qnode(dev)
+        def test_s_inverse():
+            qml.Hadamard(wires=0)
+            qml.S(wires=0).inv()
+            return qml.probs(wires=0)
+
+        test_s_inverse()
+        operations = test_s_inverse.qtape.operations if qml.tape_mode_active() else test_s_inverse.ops
+        assert "S.inv" not in [i.name for i in operations]
+        assert "PhaseShift.inv" in [i.name for i in operations]
+
+        expected = np.array([1., -1.j]) / np.sqrt(2)
+        assert np.allclose(dev.state, expected, atol=tol, rtol=0)