Repository: PennyLaneAI/pennylane-lightning
Pull request #1081: fix measurements with dynamic wires
Author: login: josephleekl
Labels: name: ci:use-multi-gpu-runner
description: Enable usage of Multi-GPU runner for this Pull Request
name: ci:use-gpu-runner
description: Enable usage of GPU runner for this Pull Request
Created: 2025-03-06T23:22:25Z | Merged: 2025-03-11T20:41:58Z

### Before submitting

Please complete the following checklist when submitting a PR:

- [ ] All new features must include a unit test.
      If you've fixed a bug or added code that should be tested, add a test to the
      [`tests`](../tests) directory!

- [ ] All new functions and code must be clearly commented and documented.
      If you do make documentation changes, make sure that the docs build and
      render correctly by running `make docs`.

- [ ] Ensure that the test suite passes, by running `make test`.

- [ ] Add a new entry to the `.github/CHANGELOG.md` file, summarizing the
      change, and including a link back to the PR.

- [ ] Ensure that code is properly formatted by running `make format`. 

When all the above are checked, delete everything above the dashed
line and fill in the pull request template.

------------------------------------------------------------------------------------------------------------

**Context:**
Currently when using dynamically determined wire count (e.g. `qml.device("lightning.qubit")` or `qml.device("lightning.qubit", shots = x)`), we have an issue when we perform measurements without specifying any observables or wires, i.e.

- qml.probs()
- qml.counts()
- qml.sample()

incorrect result is returned, since the number of wires is not known.

**Description of the Change:**
For measurements with no wires (i.e. no observables or wires provided), we edit the measurement process to include the number of wires. This is fixed for with and without shots.

**Benefits:**
Get correct results.

**Possible Drawbacks:**

**Related GitHub Issues:**
fixes https://github.com/PennyLaneAI/pennylane-lightning/issues/1086

[sc-85837]


Diff:
diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md
index 634b3c21d4..3bdc3b6f84 100644
--- a/.github/CHANGELOG.md
+++ b/.github/CHANGELOG.md
@@ -78,6 +78,9 @@
 
 ### Bug fixes
 
+* Fix measurements with empty wires and operators for statevectors with dynamically allocated wires.
+  [(#1081)](https://github.com/PennyLaneAI/pennylane-lightning/pull/1081)
+
 * Fix unit tests that were being skipped in `testApplyControlledPhaseShift`.
   [(#1083)](https://github.com/PennyLaneAI/pennylane-lightning/pull/1083)
 
diff --git a/pennylane_lightning/core/_measurements_base.py b/pennylane_lightning/core/_measurements_base.py
index 4bc8fcdc28..8fd69c728f 100644
--- a/pennylane_lightning/core/_measurements_base.py
+++ b/pennylane_lightning/core/_measurements_base.py
@@ -157,7 +157,13 @@ def probs(self, measurementprocess: MeasurementProcess):
         if diagonalizing_gates:
             self._qubit_state.apply_operations(diagonalizing_gates)
 
-        results = self._measurement_lightning.probs(measurementprocess.wires.tolist())
+        if measurementprocess.wires == Wires([]):
+            # For the case where no wires is specified for statevector
+            # and measurement process, wires are determined here
+            measurewires = self._qubit_state.wires
+        else:
+            measurewires = measurementprocess.wires.tolist()
+        results = self._measurement_lightning.probs(measurewires)
 
         if diagonalizing_gates:
             self._qubit_state.apply_operations(
@@ -310,6 +316,18 @@ def measure_with_samples(
         """
         # last N measurements are sampling MCMs in ``dynamic_one_shot`` execution mode
         mps = measurements[0 : -len(mid_measurements)] if mid_measurements else measurements
+
+        for measurement in mps:
+            if measurement.wires == Wires([]):
+                # This is required for the case where no wires is specific for the statevector
+                # (i.e. dynamically determined from circuit), and no wires (and no observable)
+                # is provided for the measurement (e.g. qml.probs() or qml.counts() or
+                # qml.samples()). In the case where number of wires is provided for the statevector,
+                # the same operation is performed in validate_device_wires during preprocess.
+
+                # pylint:disable=protected-access
+                measurement._wires = Wires(range(self._qubit_state.num_wires))
+
         groups, indices = _group_measurements(mps)
 
         all_res = []
diff --git a/pennylane_lightning/core/_version.py b/pennylane_lightning/core/_version.py
index c6ddde55ae..9b29af43ed 100644
--- a/pennylane_lightning/core/_version.py
+++ b/pennylane_lightning/core/_version.py
@@ -16,4 +16,4 @@
 Version number (major.minor.patch[-label])
 """
 
-__version__ = "0.41.0-dev32"
+__version__ = "0.41.0-dev33"
diff --git a/pennylane_lightning/lightning_tensor/_measurements.py b/pennylane_lightning/lightning_tensor/_measurements.py
index a43646d8e8..3178ae7e06 100644
--- a/pennylane_lightning/lightning_tensor/_measurements.py
+++ b/pennylane_lightning/lightning_tensor/_measurements.py
@@ -151,10 +151,18 @@ def probs(self, measurementprocess: MeasurementProcess):
             Probabilities of the supplied observable or wires
         """
         diagonalizing_gates = measurementprocess.diagonalizing_gates()
+
         if diagonalizing_gates:
             self._tensornet.apply_operations(diagonalizing_gates)
             self._tensornet.appendFinalState()
-        results = self._measurement_lightning.probs(measurementprocess.wires.tolist())
+
+        if measurementprocess.wires == Wires([]):
+            # For the case where no wires is specified for tensornet
+            # and measurement process, wires are determined here
+            measurewires = self._tensornet._wires
+        else:
+            measurewires = measurementprocess.wires.tolist()
+        results = self._measurement_lightning.probs(measurewires)
         if diagonalizing_gates:
             self._tensornet.apply_operations(
                 [qml.adjoint(g, lazy=False) for g in reversed(diagonalizing_gates)]
@@ -279,6 +287,18 @@ def measure_with_samples(
             List[TensorLike[Any]]: Sample measurement results
         """
         mps = measurements
+
+        for measurement in mps:
+            if measurement.wires == Wires([]):
+                # This is required for the case where no wires is specific for the tensornet
+                # (i.e. dynamically determined from circuit), and no wires (and no observable)
+                # is provided for the measurement (e.g. qml.probs() or qml.counts() or
+                # qml.samples()). In the case where number of wires is provided for the statevector,
+                # the same operation is performed in validate_device_wires during preprocess.
+
+                # pylint:disable=protected-access
+                measurement._wires = Wires(range(self._tensornet.num_wires))
+
         groups, indices = _group_measurements(mps)
 
         all_res = []
diff --git a/tests/test_measurements.py b/tests/test_measurements.py
index 47e087dfb2..979543b04e 100644
--- a/tests/test_measurements.py
+++ b/tests/test_measurements.py
@@ -14,6 +14,7 @@
 """
 Unit tests for Measurements in Lightning devices.
 """
+import itertools
 import math
 from typing import Sequence
 
@@ -21,9 +22,10 @@
 import pennylane as qml
 import pytest
 from conftest import LightningDevice as ld
-from conftest import device_name, lightning_ops, validate_measurements
+from conftest import LightningException, device_name, lightning_ops, validate_measurements
 from flaky import flaky
 from pennylane.measurements import ExpectationMP, Shots, VarianceMP
+from pennylane.wires import Wires
 
 if not ld._CPP_BINARY_AVAILABLE:
     pytest.skip("No binary module found. Skipping.", allow_module_level=True)
@@ -46,41 +48,61 @@ def circuit(x):
 class TestProbs:
     """Test Probs in Lightning devices"""
 
-    @pytest.fixture(params=[np.complex64, np.complex128])
+    @pytest.fixture(params=itertools.product([np.complex64, np.complex128], [None, 2]))
     def dev(self, request):
-        return qml.device(device_name, wires=2, c_dtype=request.param)
+        return qml.device(device_name, wires=request.param[1], c_dtype=request.param[0])
 
-    def test_probs_H(self, tol, dev):
+    @pytest.mark.parametrize(
+        "wire, expected", [(0, [0.5, 0.0, 0.5, 0.0]), (1, [0.5, 0.5, 0.0, 0.0])]
+    )
+    def test_probs_H(self, wire, expected, tol, dev):
         """Test probs with Hadamard"""
 
         @qml.qnode(dev)
         def circuit():
-            qml.Hadamard(wires=1)
+            qml.Hadamard(wires=wire)
             return qml.probs(wires=[0, 1])
 
-        assert np.allclose(circuit(), [0.5, 0.5, 0.0, 0.0], atol=tol, rtol=0)
+        if device_name == "lightning.tensor" and wire == 1 and dev.num_wires is None:
+            with pytest.raises(LightningException, match="Invalid wire indices order"):
+                # With dynamic wires, in this case since wires appear in this order 1, 0
+                # The wires will map 1 -> 0 and 0 -> 1. Therefore the wires in the probs
+                # measurement will be [1, 0] which is out of order and invalid for LT.
+                circuit()
+        else:
+            assert np.allclose(circuit(), expected, atol=tol, rtol=0)
 
-    @pytest.mark.parametrize(
-        "cases",
-        [
-            [None, [0.9165164490394898, 0.0, 0.08348355096051052, 0.0]],
-            [[], [0.9165164490394898, 0.0, 0.08348355096051052, 0.0]],
-        ],
-    )
-    @pytest.mark.xfail
-    def test_probs_tape_nowires(self, cases, tol, dev):
-        """Test probs with a circuit on wires=[0]"""
+    def test_probs_tape_none_wires(self, tol, dev):
+        """Test probs with a circuit with wires=None"""
+
+        x, y, z = [0.5, 0.3, -0.7]
+        expected = [0.903281826, 0.00909338007, 0.0867514634, 0.000873331009]
+        wires = None
+
+        @qml.qnode(dev)
+        def circuit():
+            qml.RX(0.4, wires=[0])
+            qml.Rot(x, y, z, wires=[0])
+            qml.RY(-0.2, wires=[1])
+            return qml.probs(wires=wires)
+
+        assert np.allclose(circuit(), expected, atol=tol, rtol=0)
+
+    def test_probs_tape_empty_wires(self, dev):
+        """Test that probs with empty list for wires raises an error"""
 
         x, y, z = [0.5, 0.3, -0.7]
+        wires = []
 
         @qml.qnode(dev)
         def circuit():
             qml.RX(0.4, wires=[0])
             qml.Rot(x, y, z, wires=[0])
             qml.RY(-0.2, wires=[0])
-            return qml.probs(wires=cases[0])
+            return qml.probs(wires=wires)
 
-        assert np.allclose(circuit(), cases[1], atol=tol, rtol=0)
+        with pytest.raises(ValueError, match="Cannot set an empty list of wires"):
+            circuit()
 
     @pytest.mark.parametrize(
         "cases",
@@ -102,7 +124,15 @@ def circuit():
             qml.RY(-0.2, wires=[0])
             return qml.probs(wires=cases[0])
 
-        assert np.allclose(circuit(), cases[1], atol=tol, rtol=0)
+        if (
+            device_name == "lightning.tensor"
+            and (isinstance(cases[0], int) or len(cases[0]) < 2)
+            and dev.num_wires is None
+        ):
+            with pytest.raises(ValueError, match="Number of wires must be greater than 1"):
+                circuit()
+        else:
+            assert np.allclose(circuit(), cases[1], atol=tol, rtol=0)
 
     @pytest.mark.skipif(
         device_name in ("lightning.tensor"),
@@ -157,27 +187,21 @@ def circuit():
 
         assert np.allclose(circuit(), cases[1], atol=tol, rtol=0)
 
-
-class TestExpval:
-    """Tests for the expval function"""
-
-    @pytest.fixture(params=[np.complex64, np.complex128])
-    def dev(self, request):
-        return qml.device(device_name, wires=2, c_dtype=request.param)
-
     @pytest.mark.parametrize(
         "cases",
         [
-            [qml.PauliX(0), -0.041892271271228736],
-            [qml.PauliX(1), 0.0],
-            [qml.PauliY(0), -0.5516350865364075],
-            [qml.PauliY(1), 0.0],
-            [qml.PauliZ(0), 0.8330328980789793],
-            [qml.PauliZ(1), 1.0],
+            [qml.PauliZ(0), [0.91237521, 0.08762479]],
+            [qml.PauliZ(1), [0.99003329, 0.00996671]],
+            [qml.PauliY(0), [0.22418248, 0.77581752]],
+            [qml.PauliY(1), [0.5, 0.5]],
+            [qml.PauliX(0), [0.56222044, 0.43777956]],
+            [qml.PauliX(1), [0.40066533, 0.59933467]],
+            [qml.Hadamard(0), [0.8355898, 0.1644102]],
+            [qml.Hadamard(1), [0.77626565, 0.22373435]],
         ],
     )
-    def test_expval_qml_tape_wire0(self, cases, tol, dev):
-        """Test expval with a circuit on wires=[0]"""
+    def test_probs_named_op(self, cases, tol, dev):
+        """Test probs with a named observable"""
 
         x, y, z = [0.5, 0.3, -0.7]
 
@@ -185,11 +209,34 @@ def test_expval_qml_tape_wire0(self, cases, tol, dev):
         def circuit():
             qml.RX(0.4, wires=[0])
             qml.Rot(x, y, z, wires=[0])
-            qml.RY(-0.2, wires=[0])
-            return qml.expval(cases[0])
+            qml.RY(-0.2, wires=[1])
+            return qml.probs(op=cases[0])
 
         assert np.allclose(circuit(), cases[1], atol=tol, rtol=0)
 
+    def test_probs_named_op_with_wires(self, dev):
+        """Test probs with a circuit on wires=[0]"""
+
+        x, y, z = [0.5, 0.3, -0.7]
+
+        @qml.qnode(dev)
+        def circuit():
+            qml.RX(0.4, wires=[0])
+            qml.Rot(x, y, z, wires=[0])
+            qml.RY(-0.2, wires=[0])
+            return qml.probs(op=qml.PauliZ(0), wires=[0])
+
+        with pytest.raises(qml.QuantumFunctionError, match="Cannot specify the wires to probs"):
+            circuit()
+
+
+class TestExpval:
+    """Tests for the expval function"""
+
+    @pytest.fixture(params=itertools.product([np.complex64, np.complex128], [None, 2]))
+    def dev(self, request):
+        return qml.device(device_name, wires=request.param[1], c_dtype=request.param[0])
+
     @pytest.mark.parametrize(
         "cases",
         [
@@ -257,12 +304,12 @@ def test_value(self, dev, tol):
         @qml.qnode(dev)
         def circuit(x):
             qml.RX(x, wires=0)
+            qml.RX(x, wires=1)
             return qml.expval(qml.PauliY(0))
 
         x = 0.54
         res = circuit(x)
         expected = -np.sin(x)
-
         assert np.allclose(res, expected, atol=tol, rtol=0)
 
     def test_not_an_observable(self, dev):
@@ -282,7 +329,8 @@ def test_observable_return_type_is_expectation(self, dev):
 
         @qml.qnode(dev)
         def circuit():
-            res = qml.expval(qml.PauliZ(0))
+            qml.PauliX(0)
+            res = qml.expval(qml.PauliZ(1))
             assert isinstance(res, ExpectationMP)
             return res
 
@@ -292,9 +340,9 @@ def circuit():
 class TestVar:
     """Tests for the var function"""
 
-    @pytest.fixture(params=[np.complex64, np.complex128])
+    @pytest.fixture(params=itertools.product([np.complex64, np.complex128], [None, 2]))
     def dev(self, request):
-        return qml.device(device_name, wires=2, c_dtype=request.param)
+        return qml.device(device_name, wires=request.param[1], c_dtype=request.param[0])
 
     @pytest.mark.parametrize(
         "cases",
@@ -319,7 +367,15 @@ def circuit():
             qml.RY(-0.2, wires=[0])
             return qml.var(cases[0])
 
-        assert np.allclose(circuit(), cases[1], atol=tol, rtol=0)
+        if (
+            device_name == "lightning.tensor"
+            and cases[0].wires.tolist() == [0]
+            and dev.num_wires is None
+        ):
+            with pytest.raises(ValueError, match="Number of wires must be greater than 1"):
+                circuit()
+        else:
+            assert np.allclose(circuit(), cases[1], atol=tol, rtol=0)
 
     @pytest.mark.parametrize(
         "cases",
@@ -349,6 +405,7 @@ def test_value(self, dev, tol):
         @qml.qnode(dev)
         def circuit(x):
             qml.RX(x, wires=0)
+            qml.RY(x, wires=1)
             return qml.var(qml.PauliZ(0))
 
         x = 0.54
@@ -374,6 +431,7 @@ def test_observable_return_type_is_variance(self, dev):
 
         @qml.qnode(dev)
         def circuit():
+            qml.PauliX(1)
             res = qml.var(qml.PauliZ(0))
             assert isinstance(res, VarianceMP)
             return res
@@ -381,24 +439,6 @@ def circuit():
         circuit()
 
 
-@pytest.mark.parametrize("stat_func", [qml.expval, qml.var])
-class TestBetaStatisticsError:
-    """Tests for errors arising for the beta statistics functions"""
-
-    def test_not_an_observable(self, stat_func):
-        """Test that a qml.QuantumFunctionError is raised if the provided
-        argument is not an observable"""
-        dev = qml.device(device_name, wires=2)
-
-        @qml.qnode(dev)
-        def circuit():
-            qml.RX(0.52, wires=0)
-            return qml.var(qml.RX(0.742, wires=[0]))
-
-        with pytest.raises(qml.DeviceError, match="Observable RX.*not supported"):
-            circuit()
-
-
 class TestSample:
     """Tests that samples are properly calculated."""
 
@@ -471,6 +511,8 @@ def reshape_samples(samples):
 @pytest.mark.parametrize(
     "obs",
     [
+        None,
+        [],
         [0],
         [0, 1],
         qml.PauliZ(0),
@@ -480,10 +522,10 @@ def reshape_samples(samples):
     ],
 )
 @pytest.mark.parametrize("mcmc", [False, True])
+@pytest.mark.parametrize("n_wires", [None, 3])
 @pytest.mark.parametrize("kernel_name", ["Local", "NonZeroRandom"])
-def test_shots_single_measure_obs(shots, measure_f, obs, mcmc, kernel_name):
+def test_shots_single_measure_obs(shots, measure_f, obs, n_wires, mcmc, kernel_name):
     """Tests that Lightning handles shots in a circuit where a single measurement of a common observable is performed at the end."""
-    n_qubits = 3
 
     if (
         shots is None or device_name in ("lightning.gpu", "lightning.kokkos", "lightning.tensor")
@@ -496,13 +538,16 @@ def test_shots_single_measure_obs(shots, measure_f, obs, mcmc, kernel_name):
     if measure_f in (qml.counts, qml.sample) and shots is None:
         pytest.skip("qml.counts, qml.sample do not work with shots = None.")
 
+    if measure_f in (qml.expval, qml.var) and obs is None:
+        pytest.skip("qml.expval, qml.var requires observable.")
+
     if device_name in ("lightning.gpu", "lightning.kokkos", "lightning.tensor"):
-        dev = qml.device(device_name, wires=n_qubits, shots=shots)
+        dev = qml.device(device_name, wires=n_wires, shots=shots)
     else:
         dev = qml.device(
-            device_name, wires=n_qubits, shots=shots, mcmc=mcmc, kernel_name=kernel_name
+            device_name, wires=n_wires, shots=shots, mcmc=mcmc, kernel_name=kernel_name
         )
-    dq = qml.device("default.qubit", wires=n_qubits, shots=shots)
+    dq = qml.device("default.qubit", wires=n_wires, shots=shots)
     params = [np.pi / 4, -np.pi / 4]
 
     def func(x, y):
@@ -512,13 +557,17 @@ def func(x, y):
         qml.RX(x, 2)
         return measure_f(wires=obs) if isinstance(obs, Sequence) else measure_f(op=obs)
 
-    func1 = qml.QNode(func, dev)
-    results1 = func1(*params)
+    if obs == []:
+        with pytest.raises(ValueError, match="Cannot set an empty list of wires"):
+            qml.QNode(func, dev)(*params)
+    else:
+        func1 = qml.QNode(func, dev)
+        results1 = func1(*params)
 
-    func2 = qml.QNode(func, dq)
-    results2 = func2(*params)
+        func2 = qml.QNode(func, dq)
+        results2 = func2(*params)
 
-    validate_measurements(measure_f, shots, results1, results2)
+        validate_measurements(measure_f, shots, results1, results2)
 
 
 # TODO: Add LT after extending the support for shots_vector


Reviews:
user: login: josephleekl
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-07T19:58:14Z
user: login: AmintorDusko
body: Good job! Nice integration with the tests we already have in place.
I'm assuming the coverage is showing false positives as usual. Please triple-check. (quadruplet-check?)
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-07T20:04:38Z
user: login: maliasadi
body: Thanks @josephleekl! Happy to approve :raised_hands: 
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-11T12:42:33Z
user: login: maliasadi
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-11T12:42:56Z
user: login: josephleekl
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T13:21:59Z
user: login: josephleekl
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T18:22:13Z
user: login: josephleekl
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T18:28:42Z

Review comments:
diff_hunk: @@ -137,10 +137,18 @@ def probs(self, measurementprocess: MeasurementProcess):
             Probabilities of the supplied observable or wires
         """
         diagonalizing_gates = measurementprocess.diagonalizing_gates()
+
         if diagonalizing_gates:
             self._tensornet.apply_operations(diagonalizing_gates)
             self._tensornet.appendFinalState()
-        results = self._measurement_lightning.probs(measurementprocess.wires.tolist())
+
+        if measurementprocess.wires == Wires([]):
path: pennylane_lightning/lightning_tensor/_measurements.py
user: login: josephleekl
body: Codecov false warnings here: the lines in this file are covered! https://app.codecov.io/gh/PennyLaneAI/pennylane-lightning/pull/1081/blob/pennylane_lightning/lightning_tensor/_measurements.py?dropdown=coverage
created_at: 2025-03-07T19:58:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -46,41 +47,61 @@ def circuit(x):
 class TestProbs:
     """Test Probs in Lightning devices"""
 
-    @pytest.fixture(params=[np.complex64, np.complex128])
+    @pytest.fixture(params=itertools.product([np.complex64, np.complex128], [None, 2]))
     def dev(self, request):
-        return qml.device(device_name, wires=2, c_dtype=request.param)
+        return qml.device(device_name, wires=request.param[1], c_dtype=request.param[0])
 
-    def test_probs_H(self, tol, dev):
+    @pytest.mark.parametrize(
+        "wire, expected", [(0, [0.5, 0.0, 0.5, 0.0]), (1, [0.5, 0.5, 0.0, 0.0])]
+    )
+    def test_probs_H(self, wire, expected, tol, dev):
         """Test probs with Hadamard"""
 
         @qml.qnode(dev)
         def circuit():
-            qml.Hadamard(wires=1)
+            qml.Hadamard(wires=wire)
             return qml.probs(wires=[0, 1])
 
-        assert np.allclose(circuit(), [0.5, 0.5, 0.0, 0.0], atol=tol, rtol=0)
+        if device_name == "lightning.tensor" and wire == 1 and dev.num_wires is None:
+            with pytest.raises(LightningException, match="Invalid wire indices order"):
+                # With dynamic wires, in this case since wires appear in this order 1, 0
+                # The wires will map 1 -> 0 and 0 -> 1. Therefore the wires in the probs
+                # measurement will be [1, 0] which is out of order and invalid for LT.
+                circuit()
+        else:
+            assert np.allclose(circuit(), expected, atol=tol, rtol=0)
 
-    @pytest.mark.parametrize(
-        "cases",
-        [
-            [None, [0.9165164490394898, 0.0, 0.08348355096051052, 0.0]],
-            [[], [0.9165164490394898, 0.0, 0.08348355096051052, 0.0]],
-        ],
-    )
-    @pytest.mark.xfail
-    def test_probs_tape_nowires(self, cases, tol, dev):
-        """Test probs with a circuit on wires=[0]"""
+    def test_probs_tape_none_wires(self, tol, dev):
+        """Test probs with a circuit with wires=None"""
 
         x, y, z = [0.5, 0.3, -0.7]
+        expected = [0.903281826, 0.00909338007, 0.0867514634, 0.000873331009]
+        wires = None
+
+        @qml.qnode(dev)
+        def circuit():
+            qml.RX(0.4, wires=[0])
+            qml.Rot(x, y, z, wires=[0])
+            qml.RY(-0.2, wires=[1])
+            return qml.probs(wires=wires)
+
+        assert np.allclose(circuit(), expected, atol=tol, rtol=0)
+
+    def test_probs_tape_emptywires(self, dev):
path: tests/test_measurements.py
user: login: AmintorDusko
body: ```suggestion
    def test_probs_tape_empty_wires(self, dev):
```
created_at: 2025-03-07T20:02:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -480,10 +520,10 @@ def reshape_samples(samples):
     ],
 )
 @pytest.mark.parametrize("mcmc", [False, True])
+@pytest.mark.parametrize("n_wires", [None, 3])
path: tests/test_measurements.py
user: login: maliasadi
body: ```suggestion
@pytest.mark.parametrize("n_wires", [None, Wires([]), 3])
```
created_at: 2025-03-11T12:41:20Z
author_association: MEMBER
diff_hunk: @@ -471,6 +510,7 @@ def reshape_samples(samples):
 @pytest.mark.parametrize(
     "obs",
     [
+        None,
         [0],
path: tests/test_measurements.py
user: login: maliasadi
body: ```suggestion
        None,
        [],
        [0],
```
created_at: 2025-03-11T12:42:00Z
author_association: MEMBER
diff_hunk: @@ -480,10 +520,10 @@ def reshape_samples(samples):
     ],
 )
 @pytest.mark.parametrize("mcmc", [False, True])
+@pytest.mark.parametrize("n_wires", [None, 3])
path: tests/test_measurements.py
user: login: maliasadi
body: ```suggestion
@pytest.mark.parametrize("n_wires", [None, Wires([]), 3])
```
created_at: 2025-03-11T12:42:55Z
author_association: MEMBER
diff_hunk: @@ -480,10 +520,10 @@ def reshape_samples(samples):
     ],
 )
 @pytest.mark.parametrize("mcmc", [False, True])
+@pytest.mark.parametrize("n_wires", [None, 3])
path: tests/test_measurements.py
user: login: josephleekl
body: duplicated comment
created_at: 2025-03-11T13:21:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -480,10 +520,10 @@ def reshape_samples(samples):
     ],
 )
 @pytest.mark.parametrize("mcmc", [False, True])
+@pytest.mark.parametrize("n_wires", [None, 3])
path: tests/test_measurements.py
user: login: josephleekl
body: Here n_wires is the input to the device, so it's only None or int
created_at: 2025-03-11T18:22:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -471,6 +510,7 @@ def reshape_samples(samples):
 @pytest.mark.parametrize(
     "obs",
     [
+        None,
         [0],
path: tests/test_measurements.py
user: login: josephleekl
body: measurement processes actually gives an error with wires=Wires([]) or wires=[] (ValueError: Cannot set an empty list of wires.) We have tested for probs, I can add tests for the other measurements too.
created_at: 2025-03-11T18:28:41Z
author_association: CONTRIBUTOR

PR comments:
user: login: codecov[bot]
created_at: 2025-03-06T23:26:50Z
body: ## [Codecov](https://app.codecov.io/gh/PennyLaneAI/pennylane-lightning/pull/1081?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.08%. Comparing base [(`b16bfb1`)](https://app.codecov.io/gh/PennyLaneAI/pennylane-lightning/commit/b16bfb1419b93d45f43f4ca163605549bd152524?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) to head [(`fba516f`)](https://app.codecov.io/gh/PennyLaneAI/pennylane-lightning/commit/fba516f85f84a28d8ee5f86cd55ff0f525911c8e?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).
> Report is 58 commits behind head on master.

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


```diff
@@            Coverage Diff             @@
##           master    #1081      +/-   ##
==========================================
+ Coverage   96.00%   99.08%   +3.07%     
==========================================
  Files         232      111     -121     
  Lines       39306    17114   -22192     
==========================================
- Hits        37737    16957   -20780     
+ Misses       1569      157    -1412     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/PennyLaneAI/pennylane-lightning/pull/1081?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> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE