Repository: PennyLaneAI/pennylane
Pull request #5603 (2024-04-30 18:53:00)

update has_diagonalizing_gates and remove xfail on test
**Context:**
A missing check in `has_diagonalizing_gates` was causing `CompositeOp` instances to sometimes incorrectly return `True` for `has_diagonalizing_gates`, i.e.:

```
>>> op1 = qml.PauliZ(0)
>>> op2 = qml.Rot(1.2, 2.3, 3.4, wires=0)
>>> op3 = qml.IsingZZ(4.32, wires=("a", "b"))
>>> op = qml.prod(op1, op2, op3)
>>> op.has_diagonalizing_gates    # should be False
True
```

**Description of the Change:**
Add the missing check to create consistency between for what base operators a `CompositeOp` can return `diagonalizing_gates`,  and what for what operators it returns `True` for `has_diagonalzing_gates`. 

Removes the `xfail` for the related test.

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.
lillian542: [sc-49608]
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5603?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:
> :exclamation: No coverage uploaded for pull request base (`v0.36.0-rc0@0cb913e`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#section-missing-base-commit).


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


```diff
@@              Coverage Diff               @@
##             v0.36.0-rc0    #5603   +/-   ##
==============================================
  Coverage               ?   99.69%           
==============================================
  Files                  ?      412           
  Lines                  ?    38287           
  Branches               ?        0           
==============================================
  Hits                   ?    38169           
  Misses                 ?      118           
  Partials               ?        0           
```



</details>

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


Patch:
diff --git a/doc/releases/changelog-0.36.0.md b/doc/releases/changelog-0.36.0.md
index e2b5ed49d..de7721e00 100644
--- a/doc/releases/changelog-0.36.0.md
+++ b/doc/releases/changelog-0.36.0.md
@@ -681,6 +681,10 @@
 * `qml.equal` can now be used with sums and products that contain operators on no wires like `I` and `GlobalPhase`.
   [(#5562)](https://github.com/PennyLaneAI/pennylane/pull/5562)
 
+* `CompositeOp.has_diagonalizing_gates` now does a more complete check of the base operators to ensure consistency 
+  between `op.has_diagonalzing_gates` and `op.diagonalizing_gates()`
+  [(#5603)](https://github.com/PennyLaneAI/pennylane/pull/5603)
+
 <h3>Contributors ✍️</h3>
 
 This release contains contributions from (in alphabetical order):
diff --git a/pennylane/ops/op_math/composite.py b/pennylane/ops/op_math/composite.py
index 75f0ab382..4a0165026 100644
--- a/pennylane/ops/op_math/composite.py
+++ b/pennylane/ops/op_math/composite.py
@@ -233,6 +233,11 @@ class CompositeOp(Operator):
     @property
     def has_diagonalizing_gates(self):
         if self.has_overlapping_wires:
+            for ops in self.overlapping_ops:
+                # if any of the single ops doesn't have diagonalizing gates, the overall operator doesn't either
+                if len(ops) == 1 and not ops[0].has_diagonalizing_gates:
+                    return False
+            # the lists of ops with multiple operators can be handled if there is a matrix
             return self.has_matrix
 
         return all(op.has_diagonalizing_gates for op in self)


Test patch:
diff --git a/tests/ops/functions/conftest.py b/tests/ops/functions/conftest.py
index b8aa17ebc..7c5107631 100644
--- a/tests/ops/functions/conftest.py
+++ b/tests/ops/functions/conftest.py
@@ -22,7 +22,7 @@ import numpy as np
 
 import pennylane as qml
 from pennylane.operation import Operator, Operation, Observable, Tensor, Channel
-from pennylane.operation import DiagGatesUndefinedError, MatrixUndefinedError
+from pennylane.operation import MatrixUndefinedError
 from pennylane.ops.op_math.adjoint import Adjoint, AdjointObs, AdjointOperation, AdjointOpObs
 from pennylane.ops.op_math.pow import PowObs, PowOperation, PowOpObs
 
@@ -53,6 +53,7 @@ _INSTANCES_TO_TEST = [
     qml.ops.Evolution(qml.PauliX(0), 5.2),
     qml.QutritBasisState([1, 2, 0], wires=[0, 1, 2]),
     qml.resource.FirstQuantization(1, 2, 1),
+    qml.prod(qml.RX(1.1, 0), qml.RY(2.2, 0), qml.RZ(3.3, 1)),
 ]
 """Valid operator instances that could not be auto-generated."""
 
@@ -78,10 +79,6 @@ _INSTANCES_TO_FAIL = [
         qml.ops.Conditional(qml.measure(1), qml.S(0)),
         AssertionError,  # needs flattening helpers to be updated, also cannot be pickled
     ),
-    (
-        qml.prod(qml.RX(1.1, 0), qml.RY(2.2, 0), qml.RZ(3.3, 1)),
-        DiagGatesUndefinedError,  # has_diagonalizing_gates should be False
-    ),
     (
         qml.Identity(0),
         MatrixUndefinedError,  # empty decomposition, matrix differs from decomp's matrix
diff --git a/tests/ops/op_math/test_prod.py b/tests/ops/op_math/test_prod.py
index 857a25d98..211049051 100644
--- a/tests/ops/op_math/test_prod.py
+++ b/tests/ops/op_math/test_prod.py
@@ -115,8 +115,6 @@ def test_obs_attribute():
     assert obs == (X(0), X(1), X(2))
 
 
-# currently failing due to has_diagonalizing_gates logic
-@pytest.mark.xfail  # TODO: fix with story 49608
 def test_basic_validity():
     """Run basic validity checks on a prod operator."""
     op1 = qml.PauliZ(0)