Repository: PennyLaneAI/pennylane
Pull request #4855 (2023-11-17 20:37:41)

globalphase decomposes to nothing
**Context:**
GlobalPhase is a relatively new operator, and some plugins may not be able to handle it. To be consistent with the pre-GlobalPhase days, I'm making it decompose to nothing so devices will decompose it and make it disappear.

**Description of the Change:**
Implement `GlobalPhase.compute_decomposition` so it decomposes to nothing

**Benefits:**
Plugins won't break if they see it. It does have a matrix defined, but maybe some plugins need a whitelist of operators.

**Possible Drawbacks:**
Maybe plugins should fail if they see it, and maybe that's what we wanted?

**Related GitHub Issues:**
Good to merge with/before #4666 
[sc-50428]

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/4855?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Comparison is base [(`02295e4`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/commit/02295e4b173d28501b5cc1ec693fadbe2620f4c6?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) 99.66% compared to head [(`4426969`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/4855?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) 99.64%.
> Report is 1 commits behind head on master.


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #4855      +/-   ##
==========================================
- Coverage   99.66%   99.64%   -0.02%     
==========================================
  Files         382      382              
  Lines       34465    34208     -257     
==========================================
- Hits        34348    34088     -260     
- Misses        117      120       +3     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/4855?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-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 c319b1b07..1d1150fce 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -79,6 +79,9 @@
 * Simplified the logic for re-arranging states before returning.
   [(#4817)](https://github.com/PennyLaneAI/pennylane/pull/4817)
 
+* `GlobalPhase` now decomposes to nothing, in case devices do not support global phases.
+  [(#4855)](https://github.com/PennyLaneAI/pennylane/pull/4855)
+
 <h3>Breaking changes 💔</h3>
 
 * Moved `qml.cond` and the `Conditional` operation from the `transforms` folder to the `ops/op_math` folder.
diff --git a/pennylane/ops/identity.py b/pennylane/ops/identity.py
index f04ce8994..2b74b92e4 100644
--- a/pennylane/ops/identity.py
+++ b/pennylane/ops/identity.py
@@ -328,6 +328,38 @@ class GlobalPhase(Operation):
         """
         return []
 
+    @staticmethod
+    def compute_decomposition(phi, wires=None):  # pylint:disable=arguments-differ,unused-argument
+        r"""Representation of the operator as a product of other operators (static method).
+
+        .. note::
+
+            The ``GlobalPhase`` operation decomposes to an empty list of operations.
+            Support for global phase
+            was added in v0.33 and was ignored in earlier versions of PennyLane. Setting
+            global phase to decompose to nothing allows existing devices to maintain
+            current support for operations which now have ``GlobalPhase`` in the
+            decomposition pipeline.
+
+        .. math:: O = O_1 O_2 \dots O_n.
+
+        .. seealso:: :meth:`~.GlobalPhase.decomposition`.
+
+        Args:
+            phi (TensorLike): the global phase
+            wires (Iterable[Any] or Any): unused argument - the operator is applied to all wires
+
+        Returns:
+            list[Operator]: decomposition into lower level operations
+
+        **Example:**
+
+        >>> qml.GlobalPhase.compute_decomposition(1.23)
+        []
+
+        """
+        return []
+
     def matrix(self, wire_order=None):
         n_wires = len(wire_order) if wire_order else len(self.wires)
         return self.compute_matrix(self.data[0], n_wires=n_wires)
diff --git a/pennylane/ops/op_math/controlled.py b/pennylane/ops/op_math/controlled.py
index 7dcfde7f5..84659c6ef 100644
--- a/pennylane/ops/op_math/controlled.py
+++ b/pennylane/ops/op_math/controlled.py
@@ -594,6 +594,13 @@ def _decompose_no_control_values(op: "operation.Operator") -> List["operation.Op
         return None
 
     base_decomp = op.base.decomposition()
+    if len(base_decomp) == 0 and isinstance(op.base, qml.GlobalPhase):
+        warnings.warn(
+            "Controlled-GlobalPhase currently decomposes to nothing, and this will likely "
+            "produce incorrect results. Consider implementing your circuit with a different set "
+            "of operations, or use a device that natively supports GlobalPhase.",
+            UserWarning,
+        )
 
     return [Controlled(newop, op.control_wires, work_wires=op.work_wires) for newop in base_decomp]
 


Test patch:
diff --git a/tests/ops/op_math/test_controlled.py b/tests/ops/op_math/test_controlled.py
index 9536c77e6..049f7c1ed 100644
--- a/tests/ops/op_math/test_controlled.py
+++ b/tests/ops/op_math/test_controlled.py
@@ -843,6 +843,14 @@ class TestHelperMethod:
         decomp_mat = qml.matrix(op.decomposition, wire_order=op.wires)()
         assert qml.math.allclose(op.matrix(), decomp_mat)
 
+    def test_global_phase_decomp_raises_warning(self):
+        """Test that ctrl(GlobalPhase).decomposition() raises a warning."""
+        op = qml.ctrl(qml.GlobalPhase(1.23), control=[0])
+        with pytest.warns(
+            UserWarning, match="Controlled-GlobalPhase currently decomposes to nothing"
+        ):
+            assert op.decomposition() == []
+
 
 @pytest.mark.parametrize("test_expand", (False, True))
 class TestDecomposition:
diff --git a/tests/ops/qubit/test_parametric_ops.py b/tests/ops/qubit/test_parametric_ops.py
index 43a47f0d6..34ab79df3 100644
--- a/tests/ops/qubit/test_parametric_ops.py
+++ b/tests/ops/qubit/test_parametric_ops.py
@@ -4522,6 +4522,13 @@ def test_global_phase_compute_sparse_matrix(phi, n_wires):
     assert np.allclose(sparse_matrix.todense(), expected.todense())
 
 
+def test_decomposition():
+    """Test the decomposition of the GlobalPhase operation."""
+
+    assert qml.GlobalPhase.compute_decomposition(1.23) == []
+    assert qml.GlobalPhase(1.23).decomposition() == []
+
+
 control_data = [
     (qml.Rot(1, 2, 3, wires=0), Wires([])),
     (qml.RX(1.23, wires=0), Wires([])),