Repository: PennyLaneAI/pennylane
Pull request #1873 (2021-11-08 16:00:48)

[OpRefactor] Make `decomposition` a method of the main `Operator`
**Context:** Operator overhaul.

**Description of the Change:** The static `decomposition` has been moved to the `Operator` class, and a new method `decompose` has been added.

**Benefits:** Decompositions can now be obtained from specific instances of operations, and can use their stored parameters and wires. The move to `Operator` will allow the decomposition to be used as an arithmetic operation when the `Operator` class is overhauled.

**Possible Drawbacks:** [Josh has found some issues](https://github.com/PennyLaneAI/pennylane/pull/1873#discussion_r747510853) with the `decompose` method in the cases where some of the non-trainable parameters are required for constructing the decomposition.

**Related GitHub Issues:** N/A


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/1873?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
> Merging [#1873](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1873?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (ba7fa85) into [master](https://codecov.io/gh/PennyLaneAI/pennylane/commit/77a1e5bab8b06b24f06ccf02e8a1b03126ae6e6f?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (77a1e5b) will **decrease** coverage by `0.00%`.
> The diff coverage is `100.00%`.

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

```diff
@@            Coverage Diff             @@
##           master    #1873      +/-   ##
==========================================
- Coverage   98.98%   98.98%   -0.01%     
==========================================
  Files         218      218              
  Lines       16433    16407      -26     
==========================================
- Hits        16267    16240      -27     
- Misses        166      167       +1     
```


| [Impacted Files](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1873?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) | Coverage Δ | |
|---|---|---|
| [pennylane/\_qubit\_device.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1873/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL19xdWJpdF9kZXZpY2UucHk=) | `98.69% <100.00%> (ø)` | |
| [pennylane/operation.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1873/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wZXJhdGlvbi5weQ==) | `98.89% <100.00%> (-0.01%)` | :arrow_down: |
| [pennylane/ops/qubit/arithmetic\_ops.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1873/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9xdWJpdC9hcml0aG1ldGljX29wcy5weQ==) | `100.00% <100.00%> (ø)` | |
| [pennylane/ops/qubit/matrix\_ops.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1873/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9xdWJpdC9tYXRyaXhfb3BzLnB5) | `99.11% <100.00%> (-0.01%)` | :arrow_down: |
| [pennylane/ops/qubit/non\_parametric\_ops.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1873/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9xdWJpdC9ub25fcGFyYW1ldHJpY19vcHMucHk=) | `97.11% <100.00%> (-0.09%)` | :arrow_down: |
| [pennylane/ops/qubit/parametric\_ops.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1873/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9xdWJpdC9wYXJhbWV0cmljX29wcy5weQ==) | `99.82% <100.00%> (-0.18%)` | :arrow_down: |
| [pennylane/ops/qubit/qchem\_ops.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1873/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9xdWJpdC9xY2hlbV9vcHMucHk=) | `100.00% <100.00%> (ø)` | |
| [pennylane/ops/qubit/state\_preparation.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1873/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9xdWJpdC9zdGF0ZV9wcmVwYXJhdGlvbi5weQ==) | `100.00% <100.00%> (ø)` | |
| [pennylane/tape/reversible.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1873/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3RhcGUvcmV2ZXJzaWJsZS5weQ==) | `100.00% <100.00%> (ø)` | |
| [pennylane/templates/subroutines/qft.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1873/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3RlbXBsYXRlcy9zdWJyb3V0aW5lcy9xZnQucHk=) | `100.00% <100.00%> (ø)` | |
| ... and [1 more](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1873/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1873?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/1873?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Last update [77a1e5b...ba7fa85](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1873?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: I must admit, I can't stop thinking about this 🤔 

> But the alternative, to keep all methods static, is not a scalable option I fear.

Would it make sense to keep `decompositions` as a static method (same for `terms`, and `matrix`), but simply _enforce that it takes the same arguments as `__init__`_? I feel like this might solve the problem.

E.g.,

```python
class MyOp(Operation):
    def __init__(self, H, x, t, wires):
        super().__init__(H.coeffs, x, t, wires)
        self.hamiltonian = H

    @Operation.decomposition()
    def decomposition(self, H, x, t, wires):
        return [qml.ApproxTimeEvolution(H, t, wires), qml.RX(x, wires[0])]
```

where `@Operation.decomposition()` is just some 'registration' function.

So you could then do _either_:

```python
>>> MyOp.decomposition(H, x, t, wires=[0, 1])
```

_or_

```python
>>> MyOp(H, x, t, wires=[0, 1]).decomposition()
```

The ambiguity is also removed, since neither the user nor the base class makes any 'assumptions' about the signature of `decomposition` --- it always just matches the `__init__`.
mariaschuld: Oh, only consider my suggestion for the changelog, I think that would need to be updated?
glassnotes: > Oh, only consider my suggestion for the changelog, I think that would need to be updated?

My bad, forgot to update that! Thanks :) 

Patch:
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index 5a4414908..2b7bc3d08 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -13,6 +13,16 @@
 
 <h3>Improvements</h3>
 
+* A `decompose()` method has been added to the `Operator` class such that we can
+  obtain (and queue) decompositions directly from instances of operations.
+  [(#1873)](https://github.com/PennyLaneAI/pennylane/pull/1873)
+
+  ```pycon
+  >>> op = qml.PhaseShift(0.3, wires=0)
+  >>> op.decompose()
+  [RZ(0.3, wires=[0])]
+  ```
+  
 * ``qml.circuit_drawer.draw_mpl`` produces a matplotlib figure and axes given a tape.
   [(#1787)](https://github.com/PennyLaneAI/pennylane/pull/1787)
 
@@ -20,6 +30,10 @@
 
 <h3>Breaking changes</h3>
 
+* The static method `decomposition()`, formerly in the `Operation` class, has
+  been moved to the base `Operator` class.
+  [(#1873)](https://github.com/PennyLaneAI/pennylane/pull/1873)
+  
 * `DiagonalOperation` is not a separate subclass any more. 
   [(#1889)](https://github.com/PennyLaneAI/pennylane/pull/1889) 
 
@@ -51,4 +65,4 @@
 
 This release contains contributions from (in alphabetical order): 
 
-Jalani Kanem, Christina Lee, Guillermo Alonso-Linaje, Alejandro Montanez, Maria Schuld, Jay Soni
+Guillermo Alonso-Linaje, Olivia Di Matteo, Jalani Kanem, Christina Lee, Alejandro Montanez, Maria Schuld, Jay Soni
diff --git a/pennylane/_qubit_device.py b/pennylane/_qubit_device.py
index dad88462e..e21b4562b 100644
--- a/pennylane/_qubit_device.py
+++ b/pennylane/_qubit_device.py
@@ -920,7 +920,7 @@ class QubitDevice(Device):
         for op in reversed(tape.operations):
             if op.num_params > 1:
                 if isinstance(op, qml.Rot) and not op.inverse:
-                    ops = op.decomposition(*op.parameters, wires=op.wires)
+                    ops = op.decompose()
                     expanded_ops.extend(reversed(ops))
                 else:
                     raise qml.QuantumFunctionError(
diff --git a/pennylane/operation.py b/pennylane/operation.py
index ba430d39b..cad0a6b85 100644
--- a/pennylane/operation.py
+++ b/pennylane/operation.py
@@ -531,6 +531,29 @@ class Operator(abc.ABC):
         """Current parameter values."""
         return self.data.copy()
 
+    @staticmethod
+    def decomposition(*params, wires):
+        """Defines a decomposition of this operator into products of other operators.
+
+        Args:
+            params (tuple[float, int, array]): operator parameters
+            wires (Union(Sequence[int], Wires)): wires the operator acts on
+
+        Returns:
+            list[Operation]
+        """
+        raise NotImplementedError
+
+    def decompose(self):
+        """Decomposes this operator into products of other operators.
+
+        Returns:
+            list[Operation]
+        """
+        if self.num_params == 0:
+            return self.decomposition(wires=self.wires)
+        return self.decomposition(*self.parameters, wires=self.wires)
+
     def queue(self, context=qml.QueuingContext):
         """Append the operator to the Operator queue."""
         context.append(self)
@@ -709,12 +732,6 @@ class Operation(Operator):
     def inverse(self, boolean):
         self._inverse = boolean
 
-    @staticmethod
-    def decomposition(*params, wires):
-        """Returns a template decomposing the operation into other
-        quantum operations."""
-        raise NotImplementedError
-
     def expand(self):
         """Returns a tape containing the decomposed operations, rather
         than a list.
@@ -727,7 +744,7 @@ class Operation(Operator):
         tape = qml.tape.QuantumTape(do_queue=False)
 
         with tape:
-            self.decomposition(*self.data, wires=self.wires)
+            self.decompose()
 
         if not self.data:
             # original operation has no trainable parameters
diff --git a/pennylane/ops/qubit/attributes.py b/pennylane/ops/qubit/attributes.py
index 2c143a2c2..5cfafe30d 100644
--- a/pennylane/ops/qubit/attributes.py
+++ b/pennylane/ops/qubit/attributes.py
@@ -182,6 +182,6 @@ diagonal_in_z_basis = Attribute(
 )
 """Attribute: Operations that are diagonal in the computational basis.
 
-For such operations, the eigenvalues provide all necessary information to 
+For such operations, the eigenvalues provide all necessary information to
 construct the matrix representation in the computational basis.
 """
diff --git a/pennylane/ops/qubit/matrix_ops.py b/pennylane/ops/qubit/matrix_ops.py
index a586cfd0c..b459e4c06 100644
--- a/pennylane/ops/qubit/matrix_ops.py
+++ b/pennylane/ops/qubit/matrix_ops.py
@@ -53,7 +53,7 @@ class QubitUnitary(Operation):
 
             dim = 2 ** len(wires)
 
-            if U.shape != (dim, dim):
+            if qml.math.shape(U) != (dim, dim):
                 raise ValueError(
                     f"Input unitary must be of shape {(dim, dim)} to act on {len(wires)} wires."
                 )
diff --git a/pennylane/tape/reversible.py b/pennylane/tape/reversible.py
index 46ce9d9b2..ab06796be 100644
--- a/pennylane/tape/reversible.py
+++ b/pennylane/tape/reversible.py
@@ -193,7 +193,7 @@ class ReversibleTape(JacobianTape):
         between_ops = self.operations[op_idx + 1 :]
 
         if op.name == "Rot":
-            decomp = op.decomposition(*op.parameters, wires=wires)
+            decomp = op.decompose()
             generator, multiplier = decomp[p_idx].generator
             between_ops = decomp[p_idx + 1 :] + between_ops
         else:


Test patch:
diff --git a/tests/ops/qubit/test_arithmetic_ops.py b/tests/ops/qubit/test_arithmetic_ops.py
index e55562550..71cabe758 100644
--- a/tests/ops/qubit/test_arithmetic_ops.py
+++ b/tests/ops/qubit/test_arithmetic_ops.py
@@ -29,7 +29,7 @@ import pennylane as qml
 def test_adjoint_with_decomposition(op_builder):
     """Tests the ``QubitCarry`` op under adjoint and decomposition."""
     op = op_builder()
-    decomposed_ops = op.decomposition(wires=op.wires)
+    decomposed_ops = op.decompose()
     with qml.tape.QuantumTape() as adjoint_tape:
         qml.adjoint(op_builder)()
     for a, b in zip(decomposed_ops, reversed(adjoint_tape.operations)):
diff --git a/tests/ops/qubit/test_matrix_ops.py b/tests/ops/qubit/test_matrix_ops.py
index 96fffe230..6cef7e088 100644
--- a/tests/ops/qubit/test_matrix_ops.py
+++ b/tests/ops/qubit/test_matrix_ops.py
@@ -181,7 +181,7 @@ class TestQubitUnitary:
         U = qml.Toffoli(wires=[0, 1, 2]).matrix
 
         with pytest.raises(NotImplementedError, match="only supported for single- and two-qubit"):
-            qml.QubitUnitary.decomposition(U, wires=[0, 1])
+            qml.QubitUnitary.decomposition(U, wires=[0, 1, 2])
 
 
 class TestDiagonalQubitUnitary:
diff --git a/tests/ops/qubit/test_non_parametric_ops.py b/tests/ops/qubit/test_non_parametric_ops.py
index df1ef04fb..6ad6ad956 100644
--- a/tests/ops/qubit/test_non_parametric_ops.py
+++ b/tests/ops/qubit/test_non_parametric_ops.py
@@ -81,7 +81,7 @@ class TestDecompositions:
     def test_x_decomposition(self, tol):
         """Tests that the decomposition of the PauliX is correct"""
         op = qml.PauliX(wires=0)
-        res = op.decomposition(0)
+        res = op.decompose()
 
         assert len(res) == 3
 
@@ -104,7 +104,7 @@ class TestDecompositions:
     def test_y_decomposition(self, tol):
         """Tests that the decomposition of the PauliY is correct"""
         op = qml.PauliY(wires=0)
-        res = op.decomposition(0)
+        res = op.decompose()
 
         assert len(res) == 3
 
@@ -127,7 +127,7 @@ class TestDecompositions:
     def test_z_decomposition(self, tol):
         """Tests that the decomposition of the PauliZ is correct"""
         op = qml.PauliZ(wires=0)
-        res = op.decomposition(0)
+        res = op.decompose()
 
         assert len(res) == 1
 
@@ -142,7 +142,7 @@ class TestDecompositions:
     def test_s_decomposition(self, tol):
         """Tests that the decomposition of the S gate is correct"""
         op = qml.S(wires=0)
-        res = op.decomposition(0)
+        res = op.decompose()
 
         assert len(res) == 1
 
@@ -157,7 +157,7 @@ class TestDecompositions:
     def test_t_decomposition(self, tol):
         """Tests that the decomposition of the T gate is correct"""
         op = qml.T(wires=0)
-        res = op.decomposition(0)
+        res = op.decompose()
 
         assert len(res) == 1
 
@@ -172,7 +172,7 @@ class TestDecompositions:
     def test_sx_decomposition(self, tol):
         """Tests that the decomposition of the SX gate is correct"""
         op = qml.SX(wires=0)
-        res = op.decomposition(0)
+        res = op.decompose()
 
         assert len(res) == 4
 
@@ -194,7 +194,7 @@ class TestDecompositions:
     def test_hadamard_decomposition(self, tol):
         """Tests that the decomposition of the Hadamard gate is correct"""
         op = qml.Hadamard(wires=0)
-        res = op.decomposition(0)
+        res = op.decompose()
 
         assert len(res) == 3
 
@@ -217,7 +217,7 @@ class TestDecompositions:
     def test_CY_decomposition(self, tol):
         """Tests that the decomposition of the CY gate is correct"""
         op = qml.CY(wires=[0, 1])
-        res = op.decomposition(op.wires)
+        res = op.decompose()
 
         mats = []
         for i in reversed(res):
@@ -232,7 +232,7 @@ class TestDecompositions:
     def test_ISWAP_decomposition(self, tol):
         """Tests that the decomposition of the ISWAP gate is correct"""
         op = qml.ISWAP(wires=[0, 1])
-        res = op.decomposition(op.wires)
+        res = op.decompose()
 
         assert len(res) == 6
 
@@ -269,7 +269,7 @@ class TestDecompositions:
     def test_SISWAP_decomposition(self, siswap_op, tol):
         """Tests that the decomposition of the SISWAP gate and its SQISW alias gate is correct"""
         op = siswap_op(wires=[0, 1])
-        res = op.decomposition(op.wires)
+        res = op.decompose()
 
         assert len(res) == 12
 
@@ -317,7 +317,7 @@ class TestDecompositions:
     def test_toffoli_decomposition(self, tol):
         """Tests that the decomposition of the Toffoli gate is correct"""
         op = qml.Toffoli(wires=[0, 1, 2])
-        res = op.decomposition(op.wires)
+        res = op.decompose()
 
         assert len(res) == 15
 
@@ -357,7 +357,7 @@ class TestDecompositions:
     def test_CSWAP_decomposition(self, tol):
         """Tests that the decomposition of the CSWAP gate is correct"""
         op = qml.CSWAP(wires=[0, 1, 2])
-        res = op.decomposition(op.wires)
+        res = op.decompose()
 
         assert len(res) == 3
 
@@ -402,7 +402,7 @@ class TestDecompositions:
     def test_swap_decomposition(self):
         """Tests the swap operator produces the correct output"""
         opr = qml.SWAP(wires=[0, 1])
-        decomp = opr.decomposition([0, 1])
+        decomp = opr.decompose()
 
         mat = []
         for op in reversed(decomp):
@@ -595,7 +595,7 @@ class TestMultiControlledX:
             f"At least one work wire is required to decompose operation: {re.escape(op.__repr__())}"
         )
         with pytest.raises(ValueError, match=match):
-            op.decomposition()
+            op.decompose()
 
     def test_not_unique_wires(self):
         """Test that a ValueError is raised when work_wires is not complementary to control_wires"""
diff --git a/tests/ops/qubit/test_parametric_ops.py b/tests/ops/qubit/test_parametric_ops.py
index 6ef497442..d9b0d4ed9 100644
--- a/tests/ops/qubit/test_parametric_ops.py
+++ b/tests/ops/qubit/test_parametric_ops.py
@@ -101,7 +101,7 @@ class TestDecompositions:
         """Tests that the decomposition of the Phase gate is correct"""
         phi = 0.3
         op = qml.PhaseShift(phi, wires=0)
-        res = op.decomposition(phi, 0)
+        res = op.decompose()
 
         assert len(res) == 1
 
@@ -119,7 +119,7 @@ class TestDecompositions:
     def test_CRot_decomposition(self, tol, phi, theta, omega, monkeypatch):
         """Tests that the decomposition of the CRot gate is correct"""
         op = qml.CRot(phi, theta, omega, wires=[0, 1])
-        res = op.decomposition(phi, theta, omega, op.wires)
+        res = op.decompose()
 
         mats = []
         for i in reversed(res):
@@ -136,7 +136,7 @@ class TestDecompositions:
         """Tests that the decomposition of the IsingXX gate is correct"""
         param = 0.1234
         op = qml.IsingXX(param, wires=[3, 2])
-        res = op.decomposition(param, op.wires)
+        res = op.decompose()
 
         assert len(res) == 3
 
@@ -164,7 +164,7 @@ class TestDecompositions:
         """Tests that the decomposition of the IsingYY gate is correct"""
         param = 0.1234
         op = qml.IsingYY(param, wires=[3, 2])
-        res = op.decomposition(param, op.wires)
+        res = op.decompose()
 
         assert len(res) == 3
 
@@ -192,7 +192,7 @@ class TestDecompositions:
         """Tests that the decomposition of the IsingZZ gate is correct"""
         param = 0.1234
         op = qml.IsingZZ(param, wires=[3, 2])
-        res = op.decomposition(param, op.wires)
+        res = op.decompose()
 
         assert len(res) == 3
 
@@ -222,7 +222,7 @@ class TestDecompositions:
         """Tests that the ControlledPhaseShift and CPhase operation
         calculates the correct decomposition"""
         op = cphase_op(phi, wires=[0, 2])
-        decomp = op.decomposition(phi, wires=[0, 2])
+        decomp = op.decompose()
 
         mats = []
         for i in reversed(decomp):
@@ -1006,7 +1006,7 @@ class TestPauliRot:
 
         theta = 0.4
         op = qml.PauliRot(theta, "Z", wires=0)
-        decomp_ops = op.decomposition(theta, "Z", wires=0)
+        decomp_ops = op.decompose()
 
         assert np.allclose(op.eigvals, np.array([np.exp(-1j * theta / 2), np.exp(1j * theta / 2)]))
         assert np.allclose(op.matrix, np.diag([np.exp(-1j * theta / 2), np.exp(1j * theta / 2)]))
@@ -1023,7 +1023,7 @@ class TestPauliRot:
 
         theta = 0.4
         op = qml.PauliRot(theta, "II", wires=[0, 1])
-        decomp_ops = op.decomposition(theta, "II", wires=[0, 1])
+        decomp_ops = op.decompose()
 
         assert np.allclose(op.eigvals, np.exp(-1j * theta / 2) * np.ones(4))
         assert np.allclose(op.matrix / op.matrix[0, 0], np.eye(4))
@@ -1035,7 +1035,7 @@ class TestPauliRot:
 
         theta = 0.4
         op = qml.PauliRot(theta, "II", wires=[0, 1])
-        decomp_ops = op.decomposition(theta, "II", wires=[0, 1])
+        decomp_ops = op.decompose()
 
         assert len(decomp_ops) == 0
 
@@ -1044,7 +1044,7 @@ class TestPauliRot:
 
         theta = 0.4
         op = qml.PauliRot(theta, "ZZ", wires=[0, 1])
-        decomp_ops = op.decomposition(theta, "ZZ", wires=[0, 1])
+        decomp_ops = op.decompose()
 
         assert len(decomp_ops) == 1
 
@@ -1058,7 +1058,7 @@ class TestPauliRot:
 
         theta = 0.4
         op = qml.PauliRot(theta, "XY", wires=[0, 1])
-        decomp_ops = op.decomposition(theta, "XY", wires=[0, 1])
+        decomp_ops = op.decompose()
 
         assert len(decomp_ops) == 5
 
@@ -1087,7 +1087,7 @@ class TestPauliRot:
 
         theta = 0.4
         op = qml.PauliRot(theta, "XIYZ", wires=[0, 1, 2, 3])
-        decomp_ops = op.decomposition(theta, "XIYZ", wires=[0, 1, 2, 3])
+        decomp_ops = op.decompose()
 
         assert len(decomp_ops) == 5
 
@@ -1146,7 +1146,6 @@ class TestPauliRot:
         @qml.qnode(dev)
         def decomp_circuit(theta):
             qml.PauliRot.decomposition(theta, "XX", wires=[0, 1])
-
             return qml.expval(qml.PauliZ(0))
 
         assert circuit(angle) == pytest.approx(decomp_circuit(angle), abs=tol)
@@ -1261,7 +1260,7 @@ class TestMultiRZ:
 
         theta = 0.4
         op = qml.MultiRZ(theta, wires=[0, 1])
-        decomp_ops = op.decomposition(theta, wires=[0, 1])
+        decomp_ops = op.decompose()
 
         assert decomp_ops[0].name == "CNOT"
         assert decomp_ops[0].wires == Wires([1, 0])
@@ -1279,7 +1278,7 @@ class TestMultiRZ:
 
         theta = 0.4
         op = qml.MultiRZ(theta, wires=[0, 2, 3])
-        decomp_ops = op.decomposition(theta, wires=[0, 2, 3])
+        decomp_ops = op.decompose()
 
         assert decomp_ops[0].name == "CNOT"
         assert decomp_ops[0].wires == Wires([3, 2])
diff --git a/tests/ops/qubit/test_qchem_ops.py b/tests/ops/qubit/test_qchem_ops.py
index d21cdac13..c99065024 100644
--- a/tests/ops/qubit/test_qchem_ops.py
+++ b/tests/ops/qubit/test_qchem_ops.py
@@ -44,7 +44,7 @@ class TestDecomposition:
         and the target is wire 0 in the decomposition. (Not applicable for
         ControlledPhase as it has the same matrix representation regardless of the
         control and target wires.)"""
-        decomp = qml.SingleExcitationPlus.decomposition(phi, wires=[0, 1])
+        decomp = qml.SingleExcitationPlus(phi, wires=[0, 1]).decompose()
 
         mats = []
         for i in reversed(decomp):
@@ -79,7 +79,7 @@ class TestDecomposition:
         and the target is wire 0 in the decomposition. (Not applicable for
         ControlledPhase as it has the same matrix representation regardless of the
         control and target wires.)"""
-        decomp = qml.SingleExcitationMinus.decomposition(phi, wires=[0, 1])
+        decomp = qml.SingleExcitationMinus(phi, wires=[0, 1]).decompose()
 
         mats = []
         for i in reversed(decomp):
@@ -122,7 +122,7 @@ class TestSingleExcitation:
 
         Need to consider the matrix of CRY separately, as the control is wire 1
         and the target is wire 0 in the decomposition."""
-        decomp = qml.SingleExcitation.decomposition(phi, wires=[0, 1])
+        decomp = qml.SingleExcitation(phi, wires=[0, 1]).decompose()
 
         mats = []
         for i in reversed(decomp):
@@ -301,7 +301,7 @@ class TestDoubleExcitation:
     def test_double_excitation_decomp(self, phi):
         """Tests that the DoubleExcitation operation calculates the correct decomposition"""
         op = qml.DoubleExcitation(phi, wires=[0, 1, 2, 3])
-        decomp = op.decomposition(phi, wires=[0, 1, 2, 3])
+        decomp = op.decomposition()
 
         mats = [m.matrix for m in decomp]
         decomposed_matrix = mats[0] @ mats[1]
@@ -328,7 +328,7 @@ class TestDoubleExcitation:
         and CNOTs. For each term in the decomposition we need to construct the appropriate
         four-qubit tensor product matrix and then multiply them together.
         """
-        decomp = qml.DoubleExcitation.decomposition(phi, wires=[0, 1, 2, 3])
+        decomp = qml.DoubleExcitation(phi, wires=[0, 1, 2, 3]).decompose()
 
         from functools import reduce
 
@@ -594,7 +594,7 @@ class TestOrbitalRotation:
         and CNOTs. For each term in the decomposition we need to construct the appropriate
         four-qubit tensor product matrix and then multiply them together.
         """
-        decomp = qml.OrbitalRotation.decomposition(phi, wires=[0, 1, 2, 3])
+        decomp = qml.OrbitalRotation(phi, wires=[0, 1, 2, 3]).decompose()
 
         from functools import reduce
 
diff --git a/tests/templates/test_subroutines/test_qft.py b/tests/templates/test_subroutines/test_qft.py
index f90709b1a..7a1baa3f6 100644
--- a/tests/templates/test_subroutines/test_qft.py
+++ b/tests/templates/test_subroutines/test_qft.py
@@ -37,7 +37,7 @@ class TestQFT:
     def test_QFT_decomposition(self, n_qubits):
         """Test if the QFT operation is correctly decomposed"""
         op = qml.QFT(wires=range(n_qubits))
-        decomp = op.decomposition(wires=range(n_qubits))
+        decomp = op.decompose()
 
         dev = qml.device("default.qubit", wires=n_qubits)
 
diff --git a/tests/test_operation.py b/tests/test_operation.py
index 6e37ac2fc..320769c88 100644
--- a/tests/test_operation.py
+++ b/tests/test_operation.py
@@ -1234,10 +1234,23 @@ class TestTensorObservableOperations:
 class TestDecomposition:
     """Test for operation decomposition"""
 
+    def test_decomposition_with_int_wire(self):
+        """Test that the decomposition of a non-parametrized Operation works
+        when we simply pass an integer as a wire without further specification."""
+        decomp_1 = qml.PauliRot.decomposition(0.1, "X", 1)
+        decomp_2 = qml.PauliRot.decomposition(0.1, "X", [1])
+        expected_decomp = qml.PauliRot.decomposition(0.1, "X", wires=1)
+
+        for obtained_1, obtained_2, expected in zip(decomp_1, decomp_2, expected_decomp):
+            assert obtained_1.name == expected.name
+            assert np.allclose(obtained_1.parameters, expected.parameters)
+            assert obtained_2.name == expected.name
+            assert np.allclose(obtained_2.parameters, expected.parameters)
+
     def test_U1_decomposition(self):
         """Test the decomposition of the U1 gate provides the equivalent phase shift gate"""
         phi = 0.432
-        res = qml.U1.decomposition(phi, wires=0)
+        res = qml.U1(phi, wires=0).decompose()
 
         assert len(res) == 1
         assert res[0].name == "PhaseShift"
@@ -1443,7 +1456,7 @@ class TestDecomposition:
             "BasisStatePreparation",
             lambda *args: call_args.append(args),
         )
-        qml.BasisState.decomposition(n, wires=wires)
+        qml.BasisState(n, wires=wires).decompose()
 
         assert len(call_args) == 1
         assert np.array_equal(call_args[0][0], n)
@@ -1462,7 +1475,7 @@ class TestDecomposition:
             "MottonenStatePreparation",
             lambda *args: call_args.append(args),
         )
-        qml.QubitStateVector.decomposition(state, wires=wires)
+        qml.QubitStateVector(state, wires=wires).decompose()
 
         assert len(call_args) == 1
         assert np.array_equal(call_args[0][0], state)