Repository: PennyLaneAI/pennylane
Pull request #7073 (2025-03-12 02:20:03)

simplify decomposition of `qml.X`, `qml.Y`, `qml.SX` #6993
**Context:**
Extension of PR #6996 @mastotte for Issue #6993 to simplify decomposition of qml.X and qml.Y. 

**Description of the Change:**
* `compute_decomposition` of qml.SX, qml.X and qml.Y now uses one GlobalPhase instead two PhaseShifts in their decomposition.
* Changed the associated tests accordingly (the unit test seems a bit hardcoded than needed). 

**Benefits:**

**Possible Drawbacks:**
Impact functions that depend on compute_decomposition of qml.SX, qml.X and qml.Y. 

**Related GitHub Issues:**
Fixes https://github.com/PennyLaneAI/pennylane/issues/6993

Hazarre: > Same as @andrijapau, looks good to me, to be verified by CI checks :)
> 
> If you are eager, @Hazarre , you could consider improving the decompsition of `qml.SX` as well, using a GlobalPhase as well. :)

I'm a bit rusty on the math, but this should be the decomp for `SX`?
```py
        return [
            qml.RY(np.pi / 2, wires=wires),
            qml.RZ(-np.pi, wires=wires),
            qml.GlobalPhase(-np.pi / 4, wires=wires),
        ]
```
andrijapau: > > Same as @andrijapau, looks good to me, to be verified by CI checks :)
> > If you are eager, @Hazarre , you could consider improving the decompsition of `qml.SX` as well, using a GlobalPhase as well. :)
> 
> I'm a bit rusty on the math, but this should be the decomp for `SX`?
> 
> ```python
>         return [
>             qml.RY(np.pi / 2, wires=wires),
>             qml.RZ(-np.pi, wires=wires),
>             qml.GlobalPhase(-np.pi / 4, wires=wires),
>         ]
> ```

As a hint, we know that `SX` decomposes to,
```python
return [
    qml.RZ(np.pi / 2, wires=wires),
    qml.RY(np.pi / 2, wires=wires),
    qml.RZ(-np.pi, wires=wires), 
    qml.PhaseShift(np.pi / 2, wires=wires),
]
```
and you can take a look in `parametric_ops_single_qubit.py` to see what `PhaseShift` decomposes into and sub it in and simplify. 😄 

As a tip, you can always check if an operator is valid with,
```python
op = qml.SX(0)
qml.ops.functions.assert_valid(op)
```
Along with a bunch of other things, this function will test if the matrix of the custom decomposition matches the matrix of the original operator.
andrijapau: The CI has finished running and there are some failures. They seem to be straight forward to fix as pretty much all of them are failing due to a mismatch in number of output operators (expected since we adjusted the decomposition). 

Let me know if you need any assistance handling the test fixes. 👍🏼 
Hazarre: > The CI has finished running and there are some failures. They seem to be straight forward to fix as pretty much all of them are failing due to a mismatch in number of output operators (expected since we adjusted the decomposition).
> 
> Let me know if you need any assistance handling the test fixes. 👍🏼

I'm not very familiar with jax and gradient. Is there something that is relevant to the failed test suites that I can look into to understand what they are doing? 
andrijapau: > > The CI has finished running and there are some failures. They seem to be straight forward to fix as pretty much all of them are failing due to a mismatch in number of output operators (expected since we adjusted the decomposition).
> > Let me know if you need any assistance handling the test fixes. 👍🏼
> 
> I'm not very familiar with jax and gradient. Is there something that is relevant to the failed test suites that I can look into to understand what they are doing?

Thanks for reaching out! 

1. For this [failure](https://github.com/PennyLaneAI/pennylane/actions/runs/13816609293/job/38651359312?pr=7073), it is also related to the decomposition of `X` and `Y`. As you can see from the test, we are creating a circuit with a few conditional branches. Some of those branches will contain `X` and `Y`. We are then decomposing this circuit and parsing the output (don't worry too much about the details as this is all very experimental for now).

```python
    def test_cond_higher_order_primitive(self):
        """Test that the cond primitive is correctly interpreted"""
        gate_set = [qml.RX, qml.RY, qml.RZ, qml.PhaseShift]

        @DecomposeInterpreter(gate_set=gate_set)
        def f(x):
            @qml.cond(x > 2)
            def cond_f():
                qml.X(0)
                return qml.expval(qml.Z(0))

            @cond_f.else_if(x > 1)
            def _():
                qml.Y(0)
                return qml.expval(qml.Y(0))

            @cond_f.otherwise
            def _():
                qml.Z(0)
                return qml.expval(qml.X(0))

            out = cond_f()
            return out

        args = (1.5,)
        jaxpr = jax.make_jaxpr(f)(*args)
        # First 2 primitives are the conditions for the true and elif branches
        assert jaxpr.eqns[2].primitive == cond_prim

        # True branch
        branch = jaxpr.eqns[2].params["jaxpr_branches"][0]
        expected_primitives = [
            qml.PhaseShift._primitive,
            qml.RX._primitive,
            qml.PhaseShift._primitive,
            qml.Z._primitive,
            qml.measurements.ExpectationMP._obs_primitive,
        ]
        assert all(
            eqn.primitive == exp_prim for eqn, exp_prim in zip(branch.eqns, expected_primitives)
        )
```
As you can see in `expected_primitives`, we have the legacy decomposition for `X` (PhaseShift, RX, PhaseShift). Instead this should be updated to your new decomposition,
```python
        expected_primitives = [
            qml.RX._primitive,
            qml.GlobalPhase._primitive,
            qml.Z._primitive,
            qml.measurements.ExpectationMP._obs_primitive,
        ]
```
Same for `Y` below. 😄 This should result in the test passing.

2. For this [failure](https://github.com/PennyLaneAI/pennylane/actions/runs/13816609293/job/38651369639?pr=7073), don't worry about it. I think its a stochastic / flaky failure related to this gradient transform.

Let me know if that's clear. 
andrijapau: Let us know when you are ready for us to run our full CI workflow on this PR again. In case you are unfamiliar, you can run it locally by following these instructions: https://docs.pennylane.ai/en/stable/development/guide/tests.html.


Hazarre: > Let us know when you are ready for us to run our full CI workflow on this PR again. In case you are unfamiliar, you can run it locally by following these instructions: https://docs.pennylane.ai/en/stable/development/guide/tests.html.

Ok thank you! I got the failed ones working locally. 

A side note, I tried changing the SX decomposition, which seems to fail many tests that I will look into. Should I inlcude that in this PR or make a separate one?
andrijapau: > > Let us know when you are ready for us to run our full CI workflow on this PR again. In case you are unfamiliar, you can run it locally by following these instructions: https://docs.pennylane.ai/en/stable/development/guide/tests.html.
> 
> Ok thank you! I got the failed ones working locally.
> 
> A side note, I tried changing the SX decomposition, which seems to fail many tests that I will look into. Should I inlcude that in this PR or make a separate one?

Good question, you can do it in this PR. Just make sure to update the PR title / description accordingly! 😄 
Hazarre: @andrijapau can you run the CI? My computer somehow freeze if I run all tests :) 
andrijapau: > @andrijapau can you run the CI? My computer somehow freeze if I run all tests :)

Sure! Just put up a comment before I kick off CI. On another note, why does it freeze? Do you mind giving me the commands you used to execute the tests? 
Hazarre: > > @andrijapau can you run the CI? My computer somehow freeze if I run all tests :)
> 
> Sure! Just put up a comment before I kick off CI. On another note, why does it freeze? Do you mind giving me the commands you used to execute the tests?

I run `make test`, or the vscode python extension on wsl on Windows.

![image](https://github.com/user-attachments/assets/699652e5-ef5a-48e2-86ac-b38d46302d72)

andrijapau: > > > @andrijapau can you run the CI? My computer somehow freeze if I run all tests :)
> > 
> > 
> > Sure! Just put up a comment before I kick off CI. On another note, why does it freeze? Do you mind giving me the commands you used to execute the tests?
> 
> I run `make test`, or the vscode python extension on wsl on Windows, which I can select a subset or test file to run instead of all at once.
> 
> ![image](https://private-user-images.githubusercontent.com/22618565/422612740-699652e5-ef5a-48e2-86ac-b38d46302d72.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDE5NTgwMDAsIm5iZiI6MTc0MTk1NzcwMCwicGF0aCI6Ii8yMjYxODU2NS80MjI2MTI3NDAtNjk5NjUyZTUtZWY1YS00OGUyLTg2YWMtYjM4ZDQ2MzAyZDcyLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAzMTQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMzE0VDEzMDgyMFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTY3ZjZjNTBkYjlkODI1M2ZlMWM3NjE4NTc1YjkzNmFhOTM0NjM4YTczNDBlMGEzMDcyZmFjMGYxNTk1OTViOTUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.L0qs1HGtIvWxZBcEqDyhIqN1uz8uwhrGHrn48EJzZ-4)

Ah I see. Interesting. I usually run the command in the terminal so I'm not too familiar with this extension. 😄 Maybe you could try that?

`pytest tests/path/to/test.py`
andrijapau: Looks like there are only a few more tests that need fixing! Nice work so far. 🚀 

![image](https://github.com/user-attachments/assets/36a71e21-5d35-44a0-a0d5-8671d0310575)

Hazarre: > Looks like there are only a few more tests that need fixing! Nice work so far. 🚀
> 
> @Hazarre Feel free to re-request our review when you want CI to be run again.

I was able to pass the particular test suite `TestExpand` that failed in CI:
![image](https://github.com/user-attachments/assets/1e4bf3eb-00ed-431c-99ee-31b1b94d21ce)

The other ones seems fail maybe because I missed install some plugin. If that looks okay, you can re-run the CI.
```py
>       raise qml.DeviceError(
            f"Device {name} does not exist. Make sure the required plugin is installed."
        )
E       pennylane.DeviceError: Device default.gaussian does not exist. Make sure the required plugin is installed.

pennylane/devices/device_constructor.py:284: DeviceError
```

andrijapau: > > Looks like there are only a few more tests that need fixing! Nice work so far. 🚀
> > @Hazarre Feel free to re-request our review when you want CI to be run again.
> 
> I was able to pass the particular test suite `TestExpand` that failed in CI: ![image](https://private-user-images.githubusercontent.com/22618565/422914893-1e4bf3eb-00ed-431c-99ee-31b1b94d21ce.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDE5NzY3MzIsIm5iZiI6MTc0MTk3NjQzMiwicGF0aCI6Ii8yMjYxODU2NS80MjI5MTQ4OTMtMWU0YmYzZWItMDBlZC00MzFjLTk5ZWUtMzFiMWI5NGQyMWNlLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAzMTQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMzE0VDE4MjAzMlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWQ5Y2JkYTU4ZGJjMGM3YTJjZmE2ZjRiMGExOWEzZWI1ZTI3ZDg1MDBjOTYzZjEyOTI3ODNiNjI4N2M2NGFmZmEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.bylQ5OWwGEFQUBm47ALZU-1i-U2JlAKtYbiU3W1Wk4A)
> 
> The other ones seems fail maybe because I missed install some plugin. If that looks okay, you can re-run the CI.
> 
> ```python
> >       raise qml.DeviceError(
>             f"Device {name} does not exist. Make sure the required plugin is installed."
>         )
> E       pennylane.DeviceError: Device default.gaussian does not exist. Make sure the required plugin is installed.
> 
> pennylane/devices/device_constructor.py:284: DeviceError
> ```

Nice work! Yeah, I think you need to install that plugin. No worries though, I will re-run the CI. 🚀 
andrijapau: Just a few more tests that need fixing after the latest CI run,
```
=========================== short test summary info ============================
FAILED tests/transforms/test_compile.py::TestCompileIntegration::test_compile_decompose_into_basis_gates[wires0] - AssertionError
FAILED tests/transforms/test_compile.py::TestCompileIntegration::test_compile_decompose_into_basis_gates[wires1] - AssertionError
FAILED tests/transforms/test_compile.py::TestCompileIntegration::test_compile_decompose_into_basis_gates[wires2] - AssertionError
FAILED tests/transforms/test_compile.py::TestCompileIntegration::test_compile_decompose_into_basis_gates[wires3] - AssertionError
```

As a side note, you should not need to install anything to have access to `"default.gaussian"`. Could you share your local environment with me so I can see what versions of `pennylane` you are using? You can do this by running `qml.about()` in a jupyter notebook. Thanks!

Please try this MWE in your environment,
```python
import pennylane as qml

dev = qml.device('default.gaussian', wires=2)
```
when you can. 🙂 
Hazarre: > ```python
> import pennylane as qml
> 
> dev = qml.device('default.gaussian', wires=2)
> ```
> 
> when you can. It should work just fine. 🙂

The `qml.about()` pointed out that in my venv pip is not installed. Installing fixed the issues. 

I was able to resolve the test suite TestCompileIntegration that was posted above. However, I'm getting some new errors, which seems related to JAX `ConcreteArray`

![image](https://github.com/user-attachments/assets/aa396f1d-2ca9-421a-86c8-c1cdfcad4d00)



```
name = 'ConcreteArray'

    @functools.cache
    def getattr(name):
      if name in deprecations:
        message, fn = deprecations[name]
        if fn is None:  # Is the deprecation accelerated?
          raise AttributeError(message)
        warnings.warn(message, DeprecationWarning, stacklevel=2)
        return fn
>     raise AttributeError(f"module {module!r} has no attribute {name!r}")
E     AttributeError: module 'jax.core' has no attribute 'ConcreteArray'
```


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/7073?dropdown=coverage&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:
> Project coverage is 99.60%. Comparing base [(`9316731`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/commit/9316731b81d326e9298393333dba32a224303ab0?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) to head [(`b1344a5`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/commit/b1344a50e319d9d02be5029b3fef80ec05af0118?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).
> Report is 1 commits behind head on master.

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


```diff
@@           Coverage Diff           @@
##           master    #7073   +/-   ##
=======================================
  Coverage   99.60%   99.60%           
=======================================
  Files         496      496           
  Lines       47332    47332           
=======================================
  Hits        47145    47145           
  Misses        187      187           
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/7073?dropdown=coverage&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).

<details><summary>🚀 New features to boost your workflow: </summary>

- ❄ [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
andrijapau: @Hazarre, are your changes ready for review? Thanks!
Hazarre: > > > ```python
> > > import pennylane as qml
> > > 
> > > dev = qml.device('default.gaussian', wires=2)
> > > ```
> > > 
> > > 
> > >     
> > >       
> > >     
> > > 
> > >       
> > >     
> > > 
> > >     
> > >   
> > > when you can. It should work just fine. 🙂
> > 
> > 
> > The `qml.about()` pointed out that in my venv pip is not installed. Installing fixed the issues.
> > I was able to resolve the test suite TestCompileIntegration that was posted above in [ec674d6]
> > ```
> > name = 'ConcreteArray'
> > 
> >     @functools.cache
> >     def getattr(name):
> >       if name in deprecations:
> >         message, fn = deprecations[name]
> >         if fn is None:  # Is the deprecation accelerated?
> >           raise AttributeError(message)
> >         warnings.warn(message, DeprecationWarning, stacklevel=2)
> >         return fn
> > >     raise AttributeError(f"module {module!r} has no attribute {name!r}")
> > E     AttributeError: module 'jax.core' has no attribute 'ConcreteArray'
> > ```
> 
> Great! Glad to hear it works now. Regarding these `jax` related errors, it also might be an environment issue (what is your jax version?). I don't see these errors in our CI, which is good.

`pip show jax` gives:
```
Name: jax
Version: 0.5.0
Location: /home/henli/temp/pennylane/.venv/lib/python3.10/site-packages
Requires: jaxlib, ml-dtypes, numpy, opt-einsum, scipy
Required-by:
```
I remember that I installed `jax`, `torch` and some libraries separately since they aren't included in `requirement.txt` nor `requirement-dev.txt`, but it seems like they needed to be installed for tests to run. Is there a way to skip jax or torch tests? or alternatively where do I check for the versions that I need to install?
Hazarre: > @Hazarre, are your changes ready for review? Thanks!

Yes! Thank you.
andrijapau: > > > > ```python
> > > > import pennylane as qml
> > > > 
> > > > dev = qml.device('default.gaussian', wires=2)
> > > > ```
> > > > 
> > > > 
> > > >     
> > > >       
> > > >     
> > > > 
> > > >       
> > > >     
> > > > 
> > > >     
> > > >   
> > > > when you can. It should work just fine. 🙂
> > > 
> > > 
> > > The `qml.about()` pointed out that in my venv pip is not installed. Installing fixed the issues.
> > > I was able to resolve the test suite TestCompileIntegration that was posted above in [[ec674d6](https://github.com/PennyLaneAI/pennylane/commit/ec674d6fe09cc22c9d57311273e7a0e720875fd4)]
> > > ```
> > > name = 'ConcreteArray'
> > > 
> > >     @functools.cache
> > >     def getattr(name):
> > >       if name in deprecations:
> > >         message, fn = deprecations[name]
> > >         if fn is None:  # Is the deprecation accelerated?
> > >           raise AttributeError(message)
> > >         warnings.warn(message, DeprecationWarning, stacklevel=2)
> > >         return fn
> > > >     raise AttributeError(f"module {module!r} has no attribute {name!r}")
> > > E     AttributeError: module 'jax.core' has no attribute 'ConcreteArray'
> > > ```
> > 
> > 
> > Great! Glad to hear it works now. Regarding these `jax` related errors, it also might be an environment issue (what is your jax version?). I don't see these errors in our CI, which is good.
> 
> `pip show jax` gives:
> 
> ```
> Name: jax
> Version: 0.5.0
> Location: /home/henli/temp/pennylane/.venv/lib/python3.10/site-packages
> Requires: jaxlib, ml-dtypes, numpy, opt-einsum, scipy
> Required-by:
> ```
> 
> I remember that I installed `jax`, `torch` and some libraries separately since they aren't included in `requirement.txt` nor `requirement-dev.txt`, but it seems like they needed to be installed for tests to run. Is there a way to skip jax or torch tests? or alternatively where do I check for the versions that I need to install?

Ah, yes. That's the problem. Currently we only support `jax==0.4.28`. Thanks for letting me know I'll look into it. 🙂 
JerryChen97: > > > @andrijapau can you run the CI? My computer somehow freeze if I run all tests :)
> > 
> > 
> > Sure! Just put up a comment before I kick off CI. On another note, why does it freeze? Do you mind giving me the commands you used to execute the tests?
> 
> I run `make test`, or the vscode python extension on wsl on Windows, which I can select a subset or test file to run instead of all at once.
> 
> ![image](https://private-user-images.githubusercontent.com/22618565/422612740-699652e5-ef5a-48e2-86ac-b38d46302d72.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDIyMjM1MTEsIm5iZiI6MTc0MjIyMzIxMSwicGF0aCI6Ii8yMjYxODU2NS80MjI2MTI3NDAtNjk5NjUyZTUtZWY1YS00OGUyLTg2YWMtYjM4ZDQ2MzAyZDcyLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAzMTclMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMzE3VDE0NTMzMVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWU3ODU2MTNhMzllYTcxMWFhODc5ZTRmNzEyNGQ4YjdjYjdjMjAxMTAyZmVhMmJlNDFjZjczMzQ3ZGM4ZjNmM2EmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.Ln8B0XusrXLSwcLWqKHocOeAfuBn8N7hyUZdgKYc0bQ)

Hi @Hazarre ! I'm also developing and testing PL using VSCode + Testing module. It's been quite common for the Testing module to freeze computer when testing PL (sometimes even simply opening this module froze my machine) but unfortunately right now I haven't found any elegant solutions to this annoying issue. For actual practice I'll recommend leaning more on cmdline running `pytest` if you need a full test; Testing module performs better when it comes to debugging parts of the test suites.

Patch:
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index 74f0f3d7a..b90a69e5a 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -55,6 +55,9 @@
   [(#6861)](https://github.com/PennyLaneAI/pennylane/pull/6861)
 
 <h3>Improvements 🛠</h3>
+  
+* The decompositions of `qml.SX`, `qml.X` and `qml.Y` use `qml.GlobalPhase` instead of `qml.PhaseShift`.
+  [(#7073)](https://github.com/PennyLaneAI/pennylane/pull/7073)  
 
 * The `reference.qubit` device now enforces `sum(probs)==1` in `sample_state`.
   [(#7076)](https://github.com/PennyLaneAI/pennylane/pull/7076)
diff --git a/pennylane/ops/qubit/non_parametric_ops.py b/pennylane/ops/qubit/non_parametric_ops.py
index 9f69deadf..9ab7aa087 100644
--- a/pennylane/ops/qubit/non_parametric_ops.py
+++ b/pennylane/ops/qubit/non_parametric_ops.py
@@ -371,16 +371,11 @@ class PauliX(Observable, Operation):
         **Example:**
 
         >>> print(qml.X.compute_decomposition(0))
-        [PhaseShift(1.5707963267948966, wires=[0]),
-        RX(3.141592653589793, wires=[0]),
-        PhaseShift(1.5707963267948966, wires=[0])]
+        [RX(3.141592653589793, wires=[0]),
+        GlobalPhase(-1.5707963267948966, wires=[0])]
 
         """
-        return [
-            qml.PhaseShift(np.pi / 2, wires=wires),
-            qml.RX(np.pi, wires=wires),
-            qml.PhaseShift(np.pi / 2, wires=wires),
-        ]
+        return [qml.RX(np.pi, wires=wires), qml.GlobalPhase(-np.pi / 2, wires=wires)]
 
     def adjoint(self) -> "PauliX":
         return X(wires=self.wires)
@@ -572,16 +567,11 @@ class PauliY(Observable, Operation):
         **Example:**
 
         >>> print(qml.Y.compute_decomposition(0))
-        [PhaseShift(1.5707963267948966, wires=[0]),
-        RY(3.141592653589793, wires=[0]),
-        PhaseShift(1.5707963267948966, wires=[0])]
+        [RY(3.141592653589793, wires=[0]),
+        GlobalPhase(-1.5707963267948966, wires=[0])]
 
         """
-        return [
-            qml.PhaseShift(np.pi / 2, wires=wires),
-            qml.RY(np.pi, wires=wires),
-            qml.PhaseShift(np.pi / 2, wires=wires),
-        ]
+        return [qml.RY(np.pi, wires=wires), qml.GlobalPhase(-np.pi / 2, wires=wires)]
 
     def adjoint(self) -> "PauliY":
         return Y(wires=self.wires)
@@ -1183,15 +1173,15 @@ class SX(Operation):
         >>> print(qml.SX.compute_decomposition(0))
         [RZ(1.5707963267948966, wires=[0]),
         RY(1.5707963267948966, wires=[0]),
-        RZ(-3.141592653589793, wires=[0]),
-        PhaseShift(1.5707963267948966, wires=[0])]
+        RZ(-1.5707963267948966, wires=[0]),
+        GlobalPhase(-0.7853981633974483, wires=[0])]
 
         """
         return [
             qml.RZ(np.pi / 2, wires=wires),
             qml.RY(np.pi / 2, wires=wires),
-            qml.RZ(-np.pi, wires=wires),
-            qml.PhaseShift(np.pi / 2, wires=wires),
+            qml.RZ(-np.pi / 2, wires=wires),
+            qml.GlobalPhase(-np.pi / 4, wires=wires),
         ]
 
     def pow(self, z: Union[int, float]) -> list[qml.operation.Operator]:


Test patch:
diff --git a/tests/capture/transforms/test_capture_decompose.py b/tests/capture/transforms/test_capture_decompose.py
index ab247c113..d1322ffa5 100644
--- a/tests/capture/transforms/test_capture_decompose.py
+++ b/tests/capture/transforms/test_capture_decompose.py
@@ -319,7 +319,7 @@ class TestDecomposeInterpreter:
 
     def test_cond_higher_order_primitive(self):
         """Test that the cond primitive is correctly interpreted"""
-        gate_set = [qml.RX, qml.RY, qml.RZ, qml.PhaseShift]
+        gate_set = [qml.RX, qml.RY, qml.RZ, qml.GlobalPhase, qml.PhaseShift]
 
         @DecomposeInterpreter(gate_set=gate_set)
         def f(x):
@@ -349,22 +349,20 @@ class TestDecomposeInterpreter:
         # True branch
         branch = jaxpr.eqns[2].params["jaxpr_branches"][0]
         expected_primitives = [
-            qml.PhaseShift._primitive,
             qml.RX._primitive,
-            qml.PhaseShift._primitive,
+            qml.GlobalPhase._primitive,
             qml.Z._primitive,
             qml.measurements.ExpectationMP._obs_primitive,
         ]
         assert all(
             eqn.primitive == exp_prim for eqn, exp_prim in zip(branch.eqns, expected_primitives)
-        )
+        ), f"Expected: {expected_primitives}, got: {[eqn.primitive for eqn in branch.eqns]}"
 
         # Elif branch
         branch = jaxpr.eqns[2].params["jaxpr_branches"][1]
         expected_primitives = [
-            qml.PhaseShift._primitive,
             qml.RY._primitive,
-            qml.PhaseShift._primitive,
+            qml.GlobalPhase._primitive,
             qml.Y._primitive,
             qml.measurements.ExpectationMP._obs_primitive,
         ]
diff --git a/tests/ops/qubit/test_non_parametric_ops.py b/tests/ops/qubit/test_non_parametric_ops.py
index d00503474..7f9d929c3 100644
--- a/tests/ops/qubit/test_non_parametric_ops.py
+++ b/tests/ops/qubit/test_non_parametric_ops.py
@@ -150,20 +150,15 @@ class TestDecompositions:
         op = qml.PauliX(wires=0)
         res = op.decomposition()
 
-        assert len(res) == 3
-
-        assert res[0].name == "PhaseShift"
+        assert len(res) == 2
 
+        assert res[0].name == "RX"
         assert res[0].wires == Wires([0])
-        assert res[0].data[0] == np.pi / 2
+        assert res[0].data[0] == np.pi
 
-        assert res[1].name == "RX"
+        assert res[1].name == "GlobalPhase"
         assert res[1].wires == Wires([0])
-        assert res[1].data[0] == np.pi
-
-        assert res[2].name == "PhaseShift"
-        assert res[2].wires == Wires([0])
-        assert res[2].data[0] == np.pi / 2
+        assert res[1].data[0] == -np.pi / 2
 
         decomposed_matrix = np.linalg.multi_dot([i.matrix() for i in reversed(res)])
         assert np.allclose(decomposed_matrix, op.matrix(), atol=tol, rtol=0)
@@ -173,20 +168,15 @@ class TestDecompositions:
         op = qml.PauliY(wires=0)
         res = op.decomposition()
 
-        assert len(res) == 3
-
-        assert res[0].name == "PhaseShift"
+        assert len(res) == 2
 
+        assert res[0].name == "RY"
         assert res[0].wires == Wires([0])
-        assert res[0].data[0] == np.pi / 2
+        assert res[0].data[0] == np.pi
 
-        assert res[1].name == "RY"
+        assert res[1].name == "GlobalPhase"
         assert res[1].wires == Wires([0])
-        assert res[1].data[0] == np.pi
-
-        assert res[2].name == "PhaseShift"
-        assert res[2].wires == Wires([0])
-        assert res[2].data[0] == np.pi / 2
+        assert res[1].data[0] == -np.pi / 2
 
         decomposed_matrix = np.linalg.multi_dot([i.matrix() for i in reversed(res)])
         assert np.allclose(decomposed_matrix, op.matrix(), atol=tol, rtol=0)
@@ -242,18 +232,17 @@ class TestDecompositions:
         res = op.decomposition()
 
         assert len(res) == 4
-
         assert all(res[i].wires == Wires([0]) for i in range(4))
 
         assert res[0].name == "RZ"
         assert res[1].name == "RY"
         assert res[2].name == "RZ"
-        assert res[3].name == "PhaseShift"
+        assert res[3].name == "GlobalPhase"
 
         assert res[0].data[0] == np.pi / 2
         assert res[1].data[0] == np.pi / 2
-        assert res[2].data[0] == -np.pi
-        assert res[3].data[0] == np.pi / 2
+        assert res[2].data[0] == -np.pi / 2
+        assert res[3].data[0] == -np.pi / 4
 
         decomposed_matrix = np.linalg.multi_dot([i.matrix() for i in reversed(res)])
         assert np.allclose(decomposed_matrix, op.matrix(), atol=tol, rtol=0)
diff --git a/tests/tape/test_tape.py b/tests/tape/test_tape.py
index bcebab486..3176d01f6 100644
--- a/tests/tape/test_tape.py
+++ b/tests/tape/test_tape.py
@@ -890,14 +890,13 @@ class TestExpand:
 
         new_tape = tape.expand()
 
-        assert len(new_tape.operations) == 3
+        assert len(new_tape.operations) == 2
 
-        assert new_tape.operations[0].name == "PhaseShift"
-        assert new_tape.operations[1].name == "RX"
-        assert new_tape.operations[2].name == "PhaseShift"
+        assert new_tape.operations[0].name == "RX"
+        assert new_tape.operations[1].name == "GlobalPhase"
 
-        assert new_tape.num_params == 3
-        assert new_tape.get_parameters() == [np.pi / 2, np.pi, np.pi / 2]
+        assert new_tape.num_params == 2
+        assert new_tape.get_parameters() == [np.pi, -np.pi / 2]
         assert new_tape.shots is tape.shots
 
     def test_stopping_criterion(self):
@@ -931,7 +930,7 @@ class TestExpand:
             qml.probs(wires="a")
 
         new_tape = tape.expand(depth=2)
-        assert len(new_tape.operations) == 11
+        assert len(new_tape.operations) == 9
 
     @pytest.mark.parametrize("skip_first", (True, False))
     @pytest.mark.parametrize(
diff --git a/tests/transforms/test_compile.py b/tests/transforms/test_compile.py
index bea56df3e..638fbf918 100644
--- a/tests/transforms/test_compile.py
+++ b/tests/transforms/test_compile.py
@@ -328,18 +328,18 @@ class TestCompileIntegration:
 
         original_result = qnode(0.3, 0.4, 0.5)
         transformed_result = transformed_qnode(0.3, 0.4, 0.5)
-        assert np.allclose(original_result, transformed_result)
+        assert np.allclose(
+            original_result, transformed_result
+        ), f"{original_result} != {transformed_result}"
 
         names_expected = [
             "RZ",
             "RX",
             "RZ",
-            "RZ",
             "CNOT",
             "RX",
             "RZ",
             "RY",
-            "RZ",
             "RY",
             "CNOT",
             "RY",
@@ -351,13 +351,11 @@ class TestCompileIntegration:
             Wires(wires[0]),
             Wires(wires[0]),
             Wires(wires[0]),
-            Wires(wires[2]),
             Wires([wires[2], wires[1]]),
             Wires(wires[0]),
             Wires(wires[1]),
             Wires(wires[2]),
             Wires(wires[2]),
-            Wires(wires[2]),
             Wires([wires[1], wires[2]]),
             Wires(wires[2]),
             Wires([wires[1], wires[2]]),