Repository: PennyLaneAI/pennylane
Pull request #4947 (2023-12-13 21:55:15)

fix the sign on globalphase in phaseshift decomp
as title says. global phase applies a -1 to the exponent. the same was missed in a place in the clifford+T transform, so I updated that as well.

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://app.codecov.io/gh/PennyLaneAI/pennylane/pull/4947?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 [(`b5c5cca`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/commit/b5c5cca3d6c2ccd011c4a52815df19d948a99b2f?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) 99.67% compared to head [(`994cbdc`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/4947?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) 99.66%.
> Report is 1 commits behind head on master.


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


```diff
@@            Coverage Diff             @@
##           master    #4947      +/-   ##
==========================================
- Coverage   99.67%   99.66%   -0.01%     
==========================================
  Files         388      388              
  Lines       35421    35150     -271     
==========================================
- Hits        35305    35033     -272     
- Misses        116      117       +1     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/4947?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 2c933ebb4..401db9c52 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -443,6 +443,7 @@
 
 * Decomposition of `qml.PhaseShift` now uses `qml.GlobalPhase` for retaining the global phase information. 
   [(#4657)](https://github.com/PennyLaneAI/pennylane/pull/4657)
+  [(#4947)](https://github.com/PennyLaneAI/pennylane/pull/4947)
 
 * `qml.equal` for `Controlled` operators no longer returns `False` when equivalent but 
   differently-ordered sets of control wires and control values are compared.
diff --git a/pennylane/ops/qubit/parametric_ops_single_qubit.py b/pennylane/ops/qubit/parametric_ops_single_qubit.py
index 29767e482..9f28f92ed 100644
--- a/pennylane/ops/qubit/parametric_ops_single_qubit.py
+++ b/pennylane/ops/qubit/parametric_ops_single_qubit.py
@@ -499,7 +499,7 @@ class PhaseShift(Operation):
         [RZ(1.234, wires=[0])]
 
         """
-        return [RZ(phi, wires=wires), qml.GlobalPhase(phi / 2)]
+        return [RZ(phi, wires=wires), qml.GlobalPhase(-phi / 2)]
 
     def adjoint(self):
         return PhaseShift(-self.data[0], wires=self.wires)
diff --git a/pennylane/transforms/decompositions/clifford_t/clifford_t_transform.py b/pennylane/transforms/decompositions/clifford_t/clifford_t_transform.py
index 7989353e9..8a0d34c05 100644
--- a/pennylane/transforms/decompositions/clifford_t/clifford_t_transform.py
+++ b/pennylane/transforms/decompositions/clifford_t/clifford_t_transform.py
@@ -208,7 +208,7 @@ def _rot_decompose(op):
     elif isinstance(op, qml.PhaseShift):
         ops_ = _simplify_param(theta, qml.PauliZ(wires=wires))
         if ops_ is None:
-            ops_ = [qml.RZ(theta, wires=wires), qml.GlobalPhase(theta / 2)]
+            ops_ = [qml.RZ(theta, wires=wires), qml.GlobalPhase(-theta / 2)]
         else:
             ops_.append(qml.GlobalPhase(-theta / 2))
 


Test patch:
diff --git a/tests/ops/functions/test_assert_valid.py b/tests/ops/functions/test_assert_valid.py
index c3208048e..308bcf085 100644
--- a/tests/ops/functions/test_assert_valid.py
+++ b/tests/ops/functions/test_assert_valid.py
@@ -354,7 +354,6 @@ def test_generated_list_of_ops(class_to_validate):
     if fail_reason := {
         qml.Identity: "empty decomposition, matrix differs from decomp's matrix",
         qml.GlobalPhase: "empty decomposition, matrix differs from decomp's matrix",
-        qml.PhaseShift: "decomposition still needs GlobalPhase, see #4657",
     }.get(class_to_validate):
         pytest.xfail(reason=fail_reason)
     if class_to_validate.__module__[14:20] == "qutrit":
diff --git a/tests/ops/qubit/test_parametric_ops.py b/tests/ops/qubit/test_parametric_ops.py
index c80aaf170..854805de8 100644
--- a/tests/ops/qubit/test_parametric_ops.py
+++ b/tests/ops/qubit/test_parametric_ops.py
@@ -275,30 +275,11 @@ class TestDecompositions:
         global_phase = np.exp(-1j * phi / 2)[..., np.newaxis, np.newaxis]
 
         assert res[1].name == "GlobalPhase"
-        assert np.allclose(qml.matrix(res[1]), np.exp(-1j * phi / 2))
-
-        assert np.allclose(decomposed_matrix, global_phase * op.matrix(), atol=tol, rtol=0)
-
-    def test_phase_decomposition_broadcasted(self, tol):
-        """Tests that the decomposition of the broadcasted Phase gate is correct"""
-        phi = np.array([0.3, 2.1, 0.2])
-        op = qml.PhaseShift(phi, wires=0)
-        res = op.decomposition()
-
-        assert len(res) == 2
-
-        assert res[0].name == "RZ"
-
-        assert res[0].wires == Wires([0])
-        assert qml.math.allclose(res[0].data[0], np.array([0.3, 2.1, 0.2]))
-
-        decomposed_matrix = res[0].matrix()
-        global_phase = np.exp(-1j * phi / 2)[..., np.newaxis, np.newaxis]
-
-        assert res[1].name == "GlobalPhase"
-        assert np.allclose(qml.matrix(res[1]), np.exp(-1j * phi / 2))
+        assert np.allclose(qml.matrix(res[1]), np.exp(1j * phi / 2))
 
         assert np.allclose(decomposed_matrix, global_phase * op.matrix(), atol=tol, rtol=0)
+        if qml.math.shape(phi) == ():  # GlobalPhase matrix doesn't support batching
+            assert np.allclose(op.matrix(), qml.prod(*res[::-1]).matrix())
 
     def test_Rot_decomposition(self):
         """Test the decomposition of Rot."""
diff --git a/tests/transforms/test_batch_transform.py b/tests/transforms/test_batch_transform.py
index cbd91c302..20b99b2b0 100644
--- a/tests/transforms/test_batch_transform.py
+++ b/tests/transforms/test_batch_transform.py
@@ -218,7 +218,7 @@ class TestBatchTransform:
         assert input_tape.operations[0].name == "RZ"
         assert input_tape.operations[1].name == "GlobalPhase"
         assert input_tape.operations[0].parameters == [0.5]
-        assert input_tape.operations[1].parameters == [0.25]
+        assert input_tape.operations[1].parameters == [-0.25]
 
     @pytest.mark.parametrize("perform_expansion", [True, False])
     def test_expand_fn_with_kwarg(self, mocker, perform_expansion):
@@ -257,7 +257,7 @@ class TestBatchTransform:
             assert input_tape.operations[0].name == "RZ"
             assert input_tape.operations[0].parameters == [0.5]
             assert input_tape.operations[1].name == "GlobalPhase"
-            assert input_tape.operations[1].parameters == [0.25]
+            assert input_tape.operations[1].parameters == [-0.25]
         else:
             assert len(input_tape.operations) == 1
             assert input_tape.operations[0].name == "PhaseShift"
@@ -303,7 +303,7 @@ class TestBatchTransform:
             assert input_tape.operations[0].name == "RZ"
             assert input_tape.operations[0].parameters == [0.5]
             assert input_tape.operations[1].name == "GlobalPhase"
-            assert input_tape.operations[1].parameters == [0.25]
+            assert input_tape.operations[1].parameters == [-0.25]
         else:
             assert len(input_tape.operations) == 1
             assert input_tape.operations[0].name == "PhaseShift"
diff --git a/tests/transforms/test_tape_expand.py b/tests/transforms/test_tape_expand.py
index e57d06e78..3eff75985 100644
--- a/tests/transforms/test_tape_expand.py
+++ b/tests/transforms/test_tape_expand.py
@@ -230,7 +230,7 @@ class TestExpandNonunitaryGen:
         assert tape.operations[:2] == new_tape.operations[:2]
         exp_op, gph_op = new_tape.operations[2:4]
         assert exp_op.name == "RZ" and exp_op.data == (2.1,) and exp_op.wires == qml.wires.Wires(1)
-        assert gph_op.name == "GlobalPhase" and gph_op.data == (2.1 * 0.5,)
+        assert gph_op.name == "GlobalPhase" and gph_op.data == (-2.1 * 0.5,)
         assert tape.operations[3:] == new_tape.operations[4:]
 
     def test_expand_nonunitary_generator(self):
@@ -249,7 +249,7 @@ class TestExpandNonunitaryGen:
         assert tape.operations[:2] == new_tape.operations[:2]
         exp_op, gph_op = new_tape.operations[2:4]
         assert exp_op.name == "RZ" and exp_op.data == (2.1,) and exp_op.wires == qml.wires.Wires(1)
-        assert gph_op.name == "GlobalPhase" and gph_op.data == (2.1 * 0.5,)
+        assert gph_op.name == "GlobalPhase" and gph_op.data == (-2.1 * 0.5,)
         assert tape.operations[3:] == new_tape.operations[4:]
 
     def test_decompose_all_nonunitary_generator(self):