Repository: PennyLaneAI/pennylane
Pull request #5170 (2024-02-07 14:31:37)

Fix `qml.prod` when qfunc contains a single operator
**Context:**

Found internally with the script
```
@qml.prod
def my_gate():
  qml.Hadamard(wires = 0)
  #qml.Hadamard(wires = 1)

dev = qml.device("default.qubit")

U = my_gate()

@qml.qnode(dev)
def circuit():

  my_gate()

  qml.ctrl(U, control = 2)

  return qml.probs(wires = [0,1,2])

qml.draw_mpl(circuit, wire_order = [0,1,2])()
```

Basically when a qfunc only has a single operator, it doesn't get turned into a `Prod` class, so it isn't re-queued.

**Description of the Change:**

Adds special logic for processing a qfunc with a single operator.

**Benefits:**

**Possible Drawbacks:**

**Related GitHub Issues:**

[sc-56341]


codecov-commenter: ## [Codecov](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5170?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 [(`c1a813d`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/commit/c1a813d3df83479527ad6751e5431a08294664a8?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) 99.68% compared to head [(`38a0ac1`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5170?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) 99.68%.
> Report is 1 commits behind head on master.


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


```diff
@@            Coverage Diff             @@
##           master    #5170      +/-   ##
==========================================
- Coverage   99.68%   99.68%   -0.01%     
==========================================
  Files         394      394              
  Lines       36160    35892     -268     
==========================================
- Hits        36047    35778     -269     
- Misses        113      114       +1     
```



</details>

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

albi3ro: ![Screenshot 2024-02-07 at 10 31 00 AM](https://github.com/PennyLaneAI/pennylane/assets/6364575/ab41f9f3-2d66-4d08-a596-64fac7cb0e23)

But the difference is one uncovered `break` statement in `merge_rotations`, which this PR certainly didn't change.  So I'm overriding.

Patch:
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index 82522d9d5..800815331 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -333,6 +333,9 @@
 
 <h3>Bug fixes 🐛</h3>
 
+* Fixes a queuing bug when using `qml.prod` with a qfunc that queues a single operator.
+  [(#5170)](https://github.com/PennyLaneAI/pennylane/pull/5170)
+
 * The `qml.TrotterProduct` template is updated to accept `SProd` as input Hamiltonian.
   [(#5073)](https://github.com/PennyLaneAI/pennylane/pull/5073)
 
diff --git a/pennylane/ops/op_math/prod.py b/pennylane/ops/op_math/prod.py
index 25c00c084..4631aa84b 100644
--- a/pennylane/ops/op_math/prod.py
+++ b/pennylane/ops/op_math/prod.py
@@ -107,6 +107,10 @@ def prod(*ops, id=None, lazy=True):
         @wraps(fn)
         def wrapper(*args, **kwargs):
             qs = qml.tape.make_qscript(fn)(*args, **kwargs)
+            if len(qs.operations) == 1:
+                if qml.QueuingManager.recording():
+                    qml.apply(qs[0])
+                return qs[0]
             return prod(*qs.operations[::-1], id=id, lazy=lazy)
 
         return wrapper


Test patch:
diff --git a/tests/ops/op_math/test_prod.py b/tests/ops/op_math/test_prod.py
index 9e49243c5..785aa1dea 100644
--- a/tests/ops/op_math/test_prod.py
+++ b/tests/ops/op_math/test_prod.py
@@ -342,6 +342,19 @@ class TestInitialization:  # pylint:disable=too-many-public-methods
         assert qml.equal(prod_op, expected)
         assert prod_op.wires == Wires([1, 0])
 
+    def test_qfunc_single_operator(self):
+        """Test prod initialization with qfunc that queues a single operator."""
+
+        def qfunc():
+            qml.S(0)
+
+        with qml.queuing.AnnotatedQueue() as q:
+            out = prod(qfunc)()
+
+        assert len(q) == 1
+        assert q.queue[0] == qml.S(0)
+        assert out == qml.S(0)
+
     def test_qfunc_init_accepts_args_kwargs(self):
         """Tests that prod preserves args when wrapping qfuncs."""