Repository: PennyLaneAI/pennylane
Pull request #3481 (2022-12-06 18:36:17)

Update operator simplify() to use _pauli_rep (Pauli Integration #3) 
**Context:**
Update `Operator.simplify()` method for arithmetic operators to make use of the PauliSentence representation when possible. 

**Description of the Change:**
- Update `Prod`, `Sum`, `SProd` and `Pow` to use `self._pauli_rep` and cast to operator when simplifying 
- Add tests


codecov[bot]: # [Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3481?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
> Merging [#3481](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3481?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (56c289c) into [master](https://codecov.io/gh/PennyLaneAI/pennylane/commit/023e001cd437e5283a4ffa1b2f73bda38ebf4bc9?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (023e001) will **decrease** coverage by `0.02%`.
> The diff coverage is `100.00%`.

```diff
@@            Coverage Diff             @@
##           master    #3481      +/-   ##
==========================================
- Coverage   99.81%   99.79%   -0.02%     
==========================================
  Files         331      331              
  Lines       28982    28992      +10     
==========================================
+ Hits        28927    28934       +7     
- Misses         55       58       +3     
```


| [Impacted Files](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3481?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) | Coverage Δ | |
|---|---|---|
| [pennylane/ops/op\_math/pow.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3481?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9vcF9tYXRoL3Bvdy5weQ==) | `99.29% <100.00%> (+0.01%)` | :arrow_up: |
| [pennylane/ops/op\_math/prod.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3481?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9vcF9tYXRoL3Byb2QucHk=) | `100.00% <100.00%> (ø)` | |
| [pennylane/ops/op\_math/sprod.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3481?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9vcF9tYXRoL3Nwcm9kLnB5) | `96.47% <100.00%> (-3.53%)` | :arrow_down: |
| [pennylane/ops/op\_math/sum.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3481?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL29wcy9vcF9tYXRoL3N1bS5weQ==) | `98.14% <100.00%> (+0.03%)` | :arrow_up: |
| [pennylane/pauli/pauli\_arithmetic.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/3481?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL3BhdWxpL3BhdWxpX2FyaXRobWV0aWMucHk=) | `100.00% <100.00%> (ø)` | |

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)

Jaybsoni: Status Update: 
- Added missing doc strings to sprod
- Fixed an edge case with `PauliSentence.operation()` and `PauliSentence.hamiltonian` 
- Diverted simplify method to use Paulirep 

To Do: 
- Explore simplifying through various interfaces (eg. Jax and Jaxjit) 
- add test cases to prod, sum, sprod, and pow where simplify is called on ops with a valid PauliRep 
- add test cases to pauliarithmetic to cover edge case for Operation and Hamiltonian


Patch:
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index 312ff7b7b..aa85f5c61 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -721,6 +721,10 @@
   instead.
   [(#3701)](https://github.com/PennyLaneAI/pennylane/pull/3701)
 
+* `op.simplify()` for operators which are linear combinations of pauli words will use a builtin pauli representation 
+  to more efficiently compute the simplification of the operator.
+  [(#3481)](https://github.com/PennyLaneAI/pennylane/pull/3481)
+
 <h3>Deprecations</h3>
 
 * `qml.utils.sparse_hamiltonian` function has been deprecated, and usage will now raise a warning.
@@ -835,6 +839,7 @@ Romain Moyard
 Mudit Pandey
 Borja Requena
 Matthew Silverman
+Jay Soni
 Antal Száva
 Frederik Wilde
 David Wierichs
diff --git a/pennylane/ops/op_math/pow.py b/pennylane/ops/op_math/pow.py
index 42f7f81cb..ffcbb3c5a 100644
--- a/pennylane/ops/op_math/pow.py
+++ b/pennylane/ops/op_math/pow.py
@@ -208,11 +208,9 @@ class Pow(ScalarSymbolicOp):
         super().__init__(base, scalar=z, do_queue=do_queue, id=id)
 
         if isinstance(self.z, int) and self.z > 0:
-            if (
-                base_pauli_rep := getattr(
-                    self.base, "_pauli_rep", None
-                )  # pylint: disable=protected-access
-            ) is not None:
+            if (base_pauli_rep := getattr(self.base, "_pauli_rep", None)) and (
+                self.batch_size is None
+            ):
                 pr = qml.pauli.PauliSentence({})
                 for _ in range(self.z):
                     pr = pr * base_pauli_rep
@@ -339,6 +337,11 @@ class Pow(ScalarSymbolicOp):
         return Pow(base=qml.adjoint(self.base), z=self.z)
 
     def simplify(self) -> Union["Pow", Identity]:
+        # try using pauli_rep:
+        if pr := self._pauli_rep:
+            pr.simplify()
+            return pr.operation(wire_order=self.wires)
+
         base = self.base.simplify()
         try:
             ops = base.pow(z=self.z)
diff --git a/pennylane/ops/op_math/prod.py b/pennylane/ops/op_math/prod.py
index 353dadf80..d547e32d6 100644
--- a/pennylane/ops/op_math/prod.py
+++ b/pennylane/ops/op_math/prod.py
@@ -353,6 +353,11 @@ class Prod(CompositeOp):
         return new_factors.global_phase, new_factors.factors
 
     def simplify(self) -> Union["Prod", Sum]:
+        # try using pauli_rep:
+        if pr := self._pauli_rep:
+            pr.simplify()
+            return pr.operation(wire_order=self.wires)
+
         global_phase, factors = self._simplify_factors(factors=self.operands)
 
         factors = list(itertools.product(*factors))
diff --git a/pennylane/ops/op_math/sprod.py b/pennylane/ops/op_math/sprod.py
index 41165c2cf..5b21f30fa 100644
--- a/pennylane/ops/op_math/sprod.py
+++ b/pennylane/ops/op_math/sprod.py
@@ -16,6 +16,7 @@ This file contains the implementation of the SProd class which contains logic fo
 computing the scalar product of operations.
 """
 from typing import Union
+from copy import copy
 
 import pennylane as qml
 import pennylane.math as qnp
@@ -137,8 +138,13 @@ class SProd(ScalarSymbolicOp):
     def __init__(self, scalar: Union[int, float, complex], base: Operator, do_queue=True, id=None):
         super().__init__(base=base, scalar=scalar, do_queue=do_queue, id=id)
 
-        if base_pauli_rep := getattr(self.base, "_pauli_rep", None):
-            pr = {pw: qnp.dot(coeff, self.scalar) for pw, coeff in base_pauli_rep.items()}
+        if (base_pauli_rep := getattr(self.base, "_pauli_rep", None)) and (self.batch_size is None):
+            scalar = copy(self.scalar)
+            if qnp.get_interface(scalar) == "tensorflow" and not scalar.dtype.is_complex:
+                c = qnp.convert_like(1 + 0j, scalar)  # get a complex dtype in the same interface
+                scalar = qnp.cast_like(scalar, c)  # cast scalar to complex dtype
+
+            pr = {pw: qnp.dot(coeff, scalar) for pw, coeff in base_pauli_rep.items()}
             self._pauli_rep = qml.pauli.PauliSentence(pr)
         else:
             self._pauli_rep = None
@@ -170,6 +176,12 @@ class SProd(ScalarSymbolicOp):
 
     @property
     def num_params(self):
+        """Number of trainable parameters that the operator depends on.
+        Usually 1 + the number of trainable parameters for the base op.
+
+        Returns:
+            int: number of trainable parameters
+        """
         return 1 + self.base.num_params
 
     def terms(self):  # is this method necessary for this class?
@@ -194,6 +206,7 @@ class SProd(ScalarSymbolicOp):
     # pylint: disable=arguments-renamed,invalid-overridden-method
     @property
     def has_diagonalizing_gates(self):
+        """Bool: Whether the Operator returns defined diagonalizing gates."""
         return self.base.has_diagonalizing_gates
 
     def diagonalizing_gates(self):
@@ -227,10 +240,23 @@ class SProd(ScalarSymbolicOp):
         return self.scalar * self.base.eigvals()
 
     def sparse_matrix(self, wire_order=None):
+        """Computes, by default, a `scipy.sparse.csr_matrix` representation of this Tensor.
+
+        This is useful for larger qubit numbers, where the dense matrix becomes very large, while
+        consisting mostly of zero entries.
+
+        Args:
+            wire_order (Iterable): Wire labels that indicate the order of wires according to which the matrix
+                is constructed. If not provided, ``self.wires`` is used.
+
+        Returns:
+            :class:`scipy.sparse._csr.csr_matrix`: sparse matrix representation
+        """
         return self.base.sparse_matrix(wire_order=wire_order).multiply(self.scalar)
 
     @property
     def has_matrix(self):
+        """Bool: Whether or not the Operator returns a defined matrix."""
         return isinstance(self.base, qml.Hamiltonian) or self.base.has_matrix
 
     @staticmethod
@@ -251,12 +277,33 @@ class SProd(ScalarSymbolicOp):
         return None
 
     def pow(self, z):
+        """Returns the operator raised to a given power."""
         return [SProd(scalar=self.scalar**z, base=Pow(base=self.base, z=z))]
 
     def adjoint(self):
+        """Create an operation that is the adjoint of this one.
+
+        Adjointed operations are the conjugated and transposed version of the
+        original operation. Adjointed ops are equivalent to the inverted operation for unitary
+        gates.
+
+        Returns:
+            The adjointed operation.
+        """
         return SProd(scalar=qml.math.conjugate(self.scalar), base=qml.adjoint(self.base))
 
+    # pylint: disable=too-many-return-statements
     def simplify(self) -> Operator:
+        """Reduce the depth of nested operators to the minimum.
+
+        Returns:
+            .Operator: simplified operator
+        """
+        # try using pauli_rep:
+        if pr := self._pauli_rep:
+            pr.simplify()
+            return pr.operation(wire_order=self.wires)
+
         if self.scalar == 1:
             return self.base.simplify()
         if isinstance(self.base, SProd):
diff --git a/pennylane/ops/op_math/sum.py b/pennylane/ops/op_math/sum.py
index ae3ae375d..83f11c222 100644
--- a/pennylane/ops/op_math/sum.py
+++ b/pennylane/ops/op_math/sum.py
@@ -295,6 +295,11 @@ class Sum(CompositeOp):
         return new_summands
 
     def simplify(self, cutoff=1.0e-12) -> "Sum":  # pylint: disable=arguments-differ
+        # try using pauli_rep:
+        if pr := self._pauli_rep:
+            pr.simplify()
+            return pr.operation(wire_order=self.wires)
+
         new_summands = self._simplify_summands(summands=self.operands).get_summands(cutoff=cutoff)
         if new_summands:
             return Sum(*new_summands) if len(new_summands) > 1 else new_summands[0]
diff --git a/pennylane/pauli/pauli_arithmetic.py b/pennylane/pauli/pauli_arithmetic.py
index e71c701a9..6026ee75d 100644
--- a/pennylane/pauli/pauli_arithmetic.py
+++ b/pennylane/pauli/pauli_arithmetic.py
@@ -364,11 +364,12 @@ class PauliSentence(dict):
         if len(self) == 0:
             if wire_order in (None, [], wires.Wires([])):
                 raise ValueError("Can't get the operation for an empty PauliSentence.")
-            return Identity(wires=wire_order)
+            return qml.s_prod(0, Identity(wires=wire_order))
 
         summands = []
+        wire_order = wire_order or self.wires
         for pw, coeff in self.items():
-            pw_op = pw.operation(wire_order=list(self.wires))
+            pw_op = pw.operation(wire_order=list(wire_order))
             summands.append(pw_op if coeff == 1 else s_prod(coeff, pw_op))
         return summands[0] if len(summands) == 1 else qml.sum(*summands)
 
@@ -377,10 +378,11 @@ class PauliSentence(dict):
         if len(self) == 0:
             if wire_order in (None, [], wires.Wires([])):
                 raise ValueError("Can't get the Hamiltonian for an empty PauliSentence.")
-            return Hamiltonian([1], [Identity(wires=wire_order)])
+            return Hamiltonian([], [])
 
+        wire_order = wire_order or self.wires
         return sum(
-            coeff * pw.hamiltonian(wire_order=list(self.wires)) for pw, coeff in self.items()
+            coeff * pw.hamiltonian(wire_order=list(wire_order)) for pw, coeff in self.items()
         )
 
     def simplify(self, tol=1e-8):


Test patch:
diff --git a/tests/ops/op_math/test_prod.py b/tests/ops/op_math/test_prod.py
index 307360d16..60e5bea72 100644
--- a/tests/ops/op_math/test_prod.py
+++ b/tests/ops/op_math/test_prod.py
@@ -924,7 +924,7 @@ class TestSimplify:
         assert isinstance(simplified_op, qml.ops.Sum)
         for s1, s2 in zip(final_op.operands, simplified_op.operands):
             assert s1.name == s2.name
-            assert s1.wires == s2.wires
+            assert s1.wires.toset() == s2.wires.toset()
             assert s1.data == s2.data
             assert s1.arithmetic_depth == s2.arithmetic_depth
 
@@ -1044,6 +1044,49 @@ class TestSimplify:
         prod_op = qml.prod(qml.S(0), qml.Barrier(0, only_visual=True), qml.S(0)).simplify()
         assert qml.equal(prod_op.simplify(), qml.PauliZ(0))
 
+    @pytest.mark.jax
+    def test_simplify_pauli_rep_jax(self):
+        """Test that simplifying operators with a valid pauli representation works with jax interface."""
+        import jax.numpy as jnp
+
+        c1, c2, c3 = jnp.array(1.23), jnp.array(2.0), jnp.array(2.46j)
+
+        op = prod(qml.s_prod(c1, qml.PauliX(0)), qml.s_prod(c2, prod(qml.PauliY(0), qml.PauliZ(1))))
+        result = qml.s_prod(c3, prod(qml.PauliZ(0), qml.PauliZ(1)))
+        simplified_op = op.simplify()
+
+        assert qml.equal(simplified_op, result)
+
+    @pytest.mark.tf
+    def test_simplify_pauli_rep_tf(self):
+        """Test that simplifying operators with a valid pauli representation works with tf interface."""
+        import tensorflow as tf
+
+        c1, c2, c3 = tf.Variable(1.23), tf.Variable(2.0), tf.Variable(2.46j)
+
+        op = prod(qml.s_prod(c1, qml.PauliX(0)), qml.s_prod(c2, prod(qml.PauliY(0), qml.PauliZ(1))))
+        result = qml.s_prod(c3, prod(qml.PauliZ(0), qml.PauliZ(1)))
+        simplified_op = op.simplify()
+
+        assert isinstance(simplified_op, type(result))
+        assert result.wires.toset() == simplified_op.wires.toset()
+        assert result.arithmetic_depth == simplified_op.arithmetic_depth
+        assert qnp.isclose(result.data[0], simplified_op.data[0])
+        assert result.data[1:] == simplified_op.data[1:]
+
+    @pytest.mark.torch
+    def test_simplify_pauli_rep_torch(self):
+        """Test that simplifying operators with a valid pauli representation works with torch interface."""
+        import torch
+
+        c1, c2, c3 = torch.tensor(1.23), torch.tensor(2.0), torch.tensor(2.46j)
+
+        op = prod(qml.s_prod(c1, qml.PauliX(0)), qml.s_prod(c2, prod(qml.PauliY(0), qml.PauliZ(1))))
+        result = qml.s_prod(c3, prod(qml.PauliZ(0), qml.PauliZ(1)))
+        simplified_op = op.simplify()
+
+        assert qml.equal(simplified_op, result)
+
 
 class TestWrapperFunc:
     """Test wrapper function."""
diff --git a/tests/ops/op_math/test_sprod.py b/tests/ops/op_math/test_sprod.py
index 58c26d578..aefb03734 100644
--- a/tests/ops/op_math/test_sprod.py
+++ b/tests/ops/op_math/test_sprod.py
@@ -780,6 +780,49 @@ class TestSimplify:
         assert simplified_op.data == final_op.data
         assert simplified_op.arithmetic_depth == final_op.arithmetic_depth
 
+    @pytest.mark.jax
+    def test_simplify_pauli_rep_jax(self):
+        """Test that simplifying operators with a valid pauli representation works with jax interface."""
+        import jax.numpy as jnp
+
+        c1, c2, c3 = jnp.array(1.23), jnp.array(2.0), jnp.array(2.46)
+
+        op = s_prod(c1, s_prod(c2, qml.PauliX(0)))
+        result = s_prod(c3, qml.PauliX(0))
+        simplified_op = op.simplify()
+
+        assert qml.equal(simplified_op, result)
+
+    @pytest.mark.tf
+    def test_simplify_pauli_rep_tf(self):
+        """Test that simplifying operators with a valid pauli representation works with tf interface."""
+        import tensorflow as tf
+
+        c1, c2, c3 = tf.Variable(1.23), tf.Variable(2.0), tf.Variable(2.46)
+
+        op = s_prod(c1, s_prod(c2, qml.PauliX(0)))
+        result = s_prod(c3, qml.PauliX(0))
+        simplified_op = op.simplify()
+
+        assert isinstance(simplified_op, type(result))
+        assert result.wires == simplified_op.wires
+        assert result.arithmetic_depth == simplified_op.arithmetic_depth
+        assert qnp.isclose(result.data[0], simplified_op.data[0])
+        assert result.data[1:] == simplified_op.data[1:]
+
+    @pytest.mark.torch
+    def test_simplify_pauli_rep_torch(self):
+        """Test that simplifying operators with a valid pauli representation works with torch interface."""
+        import torch
+
+        c1, c2, c3 = torch.tensor(1.23), torch.tensor(2.0), torch.tensor(2.46)
+
+        op = s_prod(c1, s_prod(c2, qml.PauliX(0)))
+        result = s_prod(c3, qml.PauliX(0))
+        simplified_op = op.simplify()
+
+        assert qml.equal(simplified_op, result)
+
 
 class TestWrapperFunc:
     @pytest.mark.parametrize("op_scalar_tup", ops)
diff --git a/tests/ops/op_math/test_sum.py b/tests/ops/op_math/test_sum.py
index ee528faa9..04f875367 100644
--- a/tests/ops/op_math/test_sum.py
+++ b/tests/ops/op_math/test_sum.py
@@ -727,6 +727,61 @@ class TestSimplify:
         assert simplified_op.data == final_op.data
         assert simplified_op.arithmetic_depth == final_op.arithmetic_depth
 
+    @pytest.mark.jax
+    def test_simplify_pauli_rep_jax(self):
+        """Test that simplifying operators with a valid pauli representation works with jax interface."""
+        import jax.numpy as jnp
+
+        c1, c2, c3 = jnp.array(1.23), jnp.array(-1.23), jnp.array(0.5)
+
+        op = qml.sum(
+            qml.s_prod(c1, qml.PauliX(0)),
+            qml.s_prod(c2, qml.PauliX(0)),
+            qml.s_prod(c3, qml.PauliZ(1)),
+        )
+        result = qml.s_prod(c3, qml.PauliZ(1))
+        simplified_op = op.simplify()
+
+        assert qml.equal(simplified_op, result)
+
+    @pytest.mark.tf
+    def test_simplify_pauli_rep_tf(self):
+        """Test that simplifying operators with a valid pauli representation works with tf interface."""
+        import tensorflow as tf
+
+        c1, c2, c3 = tf.Variable(1.23), tf.Variable(-1.23), tf.Variable(0.5)
+
+        op = qml.sum(
+            qml.s_prod(c1, qml.PauliX(0)),
+            qml.s_prod(c2, qml.PauliX(0)),
+            qml.s_prod(c3, qml.PauliZ(1)),
+        )
+        result = qml.s_prod(c3, qml.PauliZ(1))
+        simplified_op = op.simplify()
+
+        assert isinstance(simplified_op, type(result))
+        assert result.wires.toset() == simplified_op.wires.toset()
+        assert result.arithmetic_depth == simplified_op.arithmetic_depth
+        assert qnp.isclose(result.data[0], simplified_op.data[0])
+        assert result.data[1:] == simplified_op.data[1:]
+
+    @pytest.mark.torch
+    def test_simplify_pauli_rep_torch(self):
+        """Test that simplifying operators with a valid pauli representation works with torch interface."""
+        import torch
+
+        c1, c2, c3 = torch.tensor(1.23), torch.tensor(-1.23), torch.tensor(0.5)
+
+        op = qml.sum(
+            qml.s_prod(c1, qml.PauliX(0)),
+            qml.s_prod(c2, qml.PauliX(0)),
+            qml.s_prod(c3, qml.PauliZ(1)),
+        )
+        result = qml.s_prod(c3, qml.PauliZ(1))
+        simplified_op = op.simplify()
+
+        assert qml.equal(simplified_op, result)
+
 
 class TestSortWires:
     """Tests for the wire sorting algorithm."""
diff --git a/tests/pauli/test_pauli_arithmetic.py b/tests/pauli/test_pauli_arithmetic.py
index 5e63ad338..c8600e69d 100644
--- a/tests/pauli/test_pauli_arithmetic.py
+++ b/tests/pauli/test_pauli_arithmetic.py
@@ -492,7 +492,8 @@ class TestPauliSentence:
     def test_operation_empty(self):
         """Test that an empty PauliSentence with wire_order returns Identity."""
         op = ps5.operation(wire_order=[0, 1])
-        id = qml.Identity(wires=[0, 1])
+        id = qml.s_prod(0.0, qml.Identity(wires=[0, 1]))
+
         assert op.name == id.name
         assert op.wires == id.wires
 
@@ -504,6 +505,13 @@ class TestPauliSentence:
         with pytest.raises(ValueError, match="Can't get the operation for an empty PauliSentence."):
             ps5.operation()
 
+    def test_operation_wire_order(self):
+        """Test that the wire_order parameter is used when the pauli representation is empty"""
+        op = ps5.operation(wire_order=["a", "b"])
+        id = qml.s_prod(0.0, qml.Identity(wires=["a", "b"]))
+
+        assert qml.equal(op, id)
+
     tup_ps_hamiltonian = (
         (PauliSentence({PauliWord({0: X}): 1}), 1 * qml.PauliX(wires=0)),
         (
@@ -534,7 +542,7 @@ class TestPauliSentence:
     def test_hamiltonian_empty(self):
         """Test that an empty PauliSentence with wire_order returns Identity."""
         op = ps5.hamiltonian(wire_order=[0, 1])
-        id = 1 * qml.Identity(wires=[0, 1])
+        id = qml.Hamiltonian([], [])
         assert op.compare(id)
 
     def test_hamiltonian_empty_error(self):
@@ -545,6 +553,13 @@ class TestPauliSentence:
         ):
             ps5.hamiltonian()
 
+    def test_hamiltonian_wire_order(self):
+        """Test that the wire_order parameter is used when the pauli representation is empty"""
+        op = ps5.hamiltonian(wire_order=["a", "b"])
+        id = qml.Hamiltonian([], [])
+
+        assert qml.equal(op, id)
+
     def test_pickling(self):
         """Check that paulisentences can be pickled and unpickled."""
         pw1 = PauliWord({2: "X", 3: "Y", 4: "Z"})