Repository: PennyLaneAI/pennylane
Pull request #5635 (2024-05-03 02:51:23)

Daily rc sync to master
Automatic sync from the release candidate to master during a feature freeze.

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5635?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.69%. Comparing base [(`b556393`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/commit/b556393f129deb5f8c449c178428c0aadd51ff2c?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) to head [(`a9d5764`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5635?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).


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


```diff
@@           Coverage Diff            @@
##           master    #5635    +/-   ##
========================================
  Coverage   99.69%   99.69%            
========================================
  Files         412      412            
  Lines       38599    38327   -272     
========================================
- Hits        38480    38209   -271     
+ Misses        119      118     -1     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5635?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/introduction/compiling_circuits.rst b/doc/introduction/compiling_circuits.rst
index 6bcf46292..5215e3f7a 100644
--- a/doc/introduction/compiling_circuits.rst
+++ b/doc/introduction/compiling_circuits.rst
@@ -44,7 +44,7 @@ RX(11.336370614359172, wires=[0])
 >>> qml.simplify(qml.ops.Pow(qml.RX(1, 0), 3))
 RX(3.0, wires=[0])
 >>> qml.simplify(qml.sum(qml.Y(3), qml.Y(3)))
-2 * Y(3)
+2.0 * Y(3)
 >>> qml.simplify(qml.RX(1, 0) @ qml.RX(1, 0))
 RX(2.0, wires=[0])
 >>> qml.simplify(qml.prod(qml.X(0), qml.Z(0)))
diff --git a/doc/introduction/inspecting_circuits.rst b/doc/introduction/inspecting_circuits.rst
index 71c8373bb..813cfb4c6 100644
--- a/doc/introduction/inspecting_circuits.rst
+++ b/doc/introduction/inspecting_circuits.rst
@@ -210,7 +210,7 @@ or to check whether two gates causally influence each other.
 Internally, the :class:`~pennylane.CircuitGraph` class constructs a ``rustworkx`` graph object.
 
 >>> type(g.graph)
-<class 'rustworkx.PyDiGraph'>
+rustworkx.PyDiGraph
 
 There is no edge between the ``Hadamard`` and the first ``CNOT``, but between consecutive ``CNOT`` gates:
 
diff --git a/doc/releases/changelog-0.36.0.md b/doc/releases/changelog-0.36.0.md
index 93a68f898..de7721e00 100644
--- a/doc/releases/changelog-0.36.0.md
+++ b/doc/releases/changelog-0.36.0.md
@@ -551,6 +551,10 @@
 
 <h3>Bug fixes 🐛</h3>
 
+* Improves the error message for setting shots on the new device interface, or trying to access a property
+  that no longer exists.
+  [(#5616)](https://github.com/PennyLaneAI/pennylane/pull/5616)
+
 * Fixed a bug where `qml.draw` and `qml.draw_mpl` incorrectly raised errors for circuits collecting statistics on mid-circuit measurements
   while using `qml.defer_measurements`.
   [(#5610)](https://github.com/PennyLaneAI/pennylane/pull/5610)
@@ -677,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/devices/device_api.py b/pennylane/devices/device_api.py
index d1f0b8d50..b472973d3 100644
--- a/pennylane/devices/device_api.py
+++ b/pennylane/devices/device_api.py
@@ -176,6 +176,14 @@ class Device(abc.ABC):
         details = f"({', '.join(details)}) " if details else ""
         return f"<{self.name} device {details}at {hex(id(self))}>"
 
+    def __getattr__(self, key):
+        raise AttributeError(
+            f"{type(self).__name__} has no attribute '{key}'."
+            " You may be looking for a property or method present in the legacy device interface."
+            f" Please consult the {type(self).__name__} documentation for an updated list of public"
+            " properties and methods."
+        )
+
     @property
     def shots(self) -> Shots:
         """Default shots for execution workflows containing this device.
@@ -186,6 +194,16 @@ class Device(abc.ABC):
         """
         return self._shots
 
+    @shots.setter
+    def shots(self, _):
+        raise AttributeError(
+            (
+                "Shots can no longer be set on a device instance. "
+                "You can set shots on a call to a QNode, on individual tapes, or "
+                "create a new device instance instead."
+            )
+        )
+
     @property
     def wires(self) -> Wires:
         """The device wires.
diff --git a/pennylane/devices/preprocess.py b/pennylane/devices/preprocess.py
index 7690903f0..2c821306a 100644
--- a/pennylane/devices/preprocess.py
+++ b/pennylane/devices/preprocess.py
@@ -23,7 +23,7 @@ from typing import Callable, Generator, Optional, Sequence, Union
 
 import pennylane as qml
 from pennylane import DeviceError, Snapshot, transform
-from pennylane.measurements import MeasurementProcess, SampleMeasurement, StateMeasurement
+from pennylane.measurements import SampleMeasurement, StateMeasurement
 from pennylane.operation import StatePrepBase, Tensor
 from pennylane.typing import Result, ResultBatch
 from pennylane.wires import WireError
@@ -230,16 +230,13 @@ def validate_adjoint_trainable_params(
                 "Differentiating with respect to the input parameters of state-prep operations "
                 "is not supported with the adjoint differentiation method."
             )
-    for k in tape.trainable_params:
-        mp_or_op = tape[tape._par_info[k]["op_idx"]]
-        if isinstance(mp_or_op, MeasurementProcess):
+    for m in tape.measurements:
+        if m.obs and qml.operation.is_trainable(m.obs):
             warnings.warn(
-                "Differentiating with respect to the input parameters of "
-                f"{mp_or_op.obs.name} is not supported with the "
-                "adjoint differentiation method. Gradients are computed "
-                "only with regards to the trainable parameters of the circuit.\n\n Mark "
-                "the parameters of the measured observables as non-trainable "
-                "to silence this warning.",
+                f"Differentiating with respect to the input parameters of {m.obs.name} "
+                "is not supported with the adjoint differentiation method. Gradients are computed "
+                "only with regards to the trainable parameters of the circuit.\n\n Mark the "
+                "parameters of the measured observables as non-trainable to silence this warning.",
                 UserWarning,
             )
     return (tape,), null_postprocessing
diff --git a/pennylane/math/fidelity.py b/pennylane/math/fidelity.py
index d8d6643f3..b338fd14c 100644
--- a/pennylane/math/fidelity.py
+++ b/pennylane/math/fidelity.py
@@ -150,6 +150,15 @@ def fidelity(state0, state1, check_state=False, c_dtype="complex128"):
     if qml.math.shape(state0)[-1] != qml.math.shape(state1)[-1]:
         raise qml.QuantumFunctionError("The two states must have the same number of wires.")
 
+    batch_size0 = qml.math.shape(state0)[0] if qml.math.ndim(state0) > 2 else None
+    batch_size1 = qml.math.shape(state1)[0] if qml.math.ndim(state1) > 2 else None
+
+    if qml.math.get_interface(state0) == "jax" or qml.math.get_interface(state1) == "jax":
+        if batch_size0 and not batch_size1:
+            state1 = qml.math.broadcast_to(state1, (batch_size0, *qml.math.shape(state1)))
+        elif not batch_size0 and batch_size1:
+            state0 = qml.math.broadcast_to(state0, (batch_size1, *qml.math.shape(state0)))
+
     # Two mixed states
     _register_vjp(state0, state1)
     fid = qml.math.compute_fidelity(state0, state1)
diff --git a/pennylane/ops/functions/dot.py b/pennylane/ops/functions/dot.py
index 6fe52d387..727aa9a09 100644
--- a/pennylane/ops/functions/dot.py
+++ b/pennylane/ops/functions/dot.py
@@ -39,7 +39,8 @@ def dot(
 
     Args:
         coeffs (Sequence[float, Callable]): sequence containing the coefficients of the linear combination
-        ops (Sequence[Operator]): sequence containing the operators of the linear combination
+        ops (Sequence[Operator, PauliWord, PauliSentence]): sequence containing the operators of the linear combination.
+           Can also be ``PauliWord`` or ``PauliSentence`` instances.
         pauli (bool, optional): If ``True``, a :class:`~.PauliSentence`
             operator is used to represent the linear combination. If False, a :class:`Sum` operator
             is returned. Defaults to ``False``. Note that when ``ops`` consists solely of ``PauliWord``
@@ -136,6 +137,12 @@ def dot(
     if len(coeffs) == 0 and len(ops) == 0:
         raise ValueError("Cannot compute the dot product of an empty sequence.")
 
+    for t in (Operator, PauliWord, PauliSentence):
+        if isinstance(ops, t):
+            raise ValueError(
+                f"ops must be an Iterable of {t.__name__}'s, not a {t.__name__} itself."
+            )
+
     if any(callable(c) for c in coeffs):
         return ParametrizedHamiltonian(coeffs, ops)
 
diff --git a/pennylane/ops/op_math/composite.py b/pennylane/ops/op_math/composite.py
index f3ba3c43c..400535c4b 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)
diff --git a/pennylane/ops/op_math/linear_combination.py b/pennylane/ops/op_math/linear_combination.py
index 7b67cc4d1..cde0c5cd8 100644
--- a/pennylane/ops/op_math/linear_combination.py
+++ b/pennylane/ops/op_math/linear_combination.py
@@ -118,6 +118,10 @@ class LinearCombination(Sum):
         _pauli_rep=None,
         id=None,
     ):
+        if isinstance(observables, Operator):
+            raise ValueError(
+                "observables must be an Iterable of Operator's, and not an Operator itself."
+            )
         if qml.math.shape(coeffs)[0] != len(observables):
             raise ValueError(
                 "Could not create valid LinearCombination; "
diff --git a/pennylane/pauli/dla/lie_closure.py b/pennylane/pauli/dla/lie_closure.py
index 336a507b8..e109c50d3 100644
--- a/pennylane/pauli/dla/lie_closure.py
+++ b/pennylane/pauli/dla/lie_closure.py
@@ -63,9 +63,9 @@ def lie_closure(
     A first round of commutators between all elements yields:
 
     >>> qml.commutator(X(0) @ X(1), Z(0))
-    -2j * (X(1) @ Y(0))
+    -2j * (Y(0) @ X(1))
     >>> qml.commutator(X(0) @ X(1), Z(1))
-    -2j * (Y(1) @ X(0))
+    -2j * (X(0) @ Y(1))
 
     A next round of commutators between all elements further yields the new operator ``Y(0) @ Y(1)``.
 
@@ -81,9 +81,9 @@ def lie_closure(
     [X(1) @ X(0),
      Z(0),
      Z(1),
-     -1.0 * (X(1) @ Y(0)),
-     -1.0 * (Y(1) @ X(0)),
-     -1.0 * (Y(1) @ Y(0))]
+     -1.0 * (Y(0) @ X(1)),
+     -1.0 * (X(0) @ Y(1)),
+     -1.0 * (Y(0) @ Y(1))]
 
     Note that we normalize by removing the factors of :math:`2i`, though minus signs are left intact.
 
@@ -305,10 +305,14 @@ class PauliVSpace:
 
         for ps in other:
             # TODO: Potential speed-up by computing the maximal linear independent set for all current basis vectors + other, essentially algorithm1 in https://arxiv.org/abs/1012.5256
-            self._M, self._pw_to_idx, self._rank, self._num_pw, is_independent = (
-                self._check_independence(
-                    self._M, ps, self._pw_to_idx, self._rank, self._num_pw, tol
-                )
+            (
+                self._M,
+                self._pw_to_idx,
+                self._rank,
+                self._num_pw,
+                is_independent,
+            ) = self._check_independence(
+                self._M, ps, self._pw_to_idx, self._rank, self._num_pw, tol
             )
             if is_independent:
                 self._basis.append(ps)
diff --git a/pennylane/pauli/dla/structure_constants.py b/pennylane/pauli/dla/structure_constants.py
index c6c2b1676..c32295f9e 100644
--- a/pennylane/pauli/dla/structure_constants.py
+++ b/pennylane/pauli/dla/structure_constants.py
@@ -75,7 +75,7 @@ def structure_constants(
     >>> gens += [Z(i) for i in range(n)]
     >>> dla = qml.lie_closure(gens)
     >>> print(dla)
-    [X(1) @ X(0), Z(0), Z(1), -1.0 * (X(1) @ Y(0)), -1.0 * (Y(1) @ X(0)), -1.0 * (Y(1) @ Y(0))]
+    [X(0) @ X(1), Z(0), Z(1), -1.0 * (Y(0) @ X(1)), -1.0 * (X(0) @ Y(1)), -1.0 * (Y(0) @ Y(1))]
 
     The dimension of the DLA is :math:`d = 6`. Hence, the structure constants have shape ``(6, 6, 6)``.
 
diff --git a/pennylane/qaoa/cycle.py b/pennylane/qaoa/cycle.py
index ab3c854ed..1fef9d749 100644
--- a/pennylane/qaoa/cycle.py
+++ b/pennylane/qaoa/cycle.py
@@ -347,7 +347,7 @@ def loss_hamiltonian(graph: Union[nx.Graph, rx.PyGraph, rx.PyDiGraph]) -> qml.op
     )
 
     >>> import rustworkx as rx
-    >>> g = rx.generators.directed_mesh_graph(3)
+    >>> g = rx.generators.directed_mesh_graph(3, [0, 1, 2])
     >>> edge_weight_data = {edge: (i + 1) * 0.5 for i, edge in enumerate(sorted(g.edge_list()))}
     >>> for k, v in edge_weight_data.items():
             g.update_edge(k[0], k[1], {"weight": v})


Test patch:
diff --git a/tests/devices/default_qubit/test_default_qubit_preprocessing.py b/tests/devices/default_qubit/test_default_qubit_preprocessing.py
index bab719750..ac5e80d2b 100644
--- a/tests/devices/default_qubit/test_default_qubit_preprocessing.py
+++ b/tests/devices/default_qubit/test_default_qubit_preprocessing.py
@@ -833,7 +833,7 @@ class TestAdjointDiffTapeValidation:
         expectation value of a Hermitian operator emits a warning if the
         parameters to Hermitian are trainable."""
 
-        mx = qml.matrix(qml.PauliX(0) @ qml.PauliY(2))
+        mx = qml.numpy.array(qml.matrix(qml.PauliX(0) @ qml.PauliY(2)))
         qs = qml.tape.QuantumScript([], [qml.expval(qml.Hermitian(mx, wires=[0, 2]))])
 
         qs.trainable_params = {0}
diff --git a/tests/devices/experimental/test_device_api.py b/tests/devices/experimental/test_device_api.py
index 2db5826f3..44a038ab8 100644
--- a/tests/devices/experimental/test_device_api.py
+++ b/tests/devices/experimental/test_device_api.py
@@ -71,9 +71,20 @@ class TestMinimalDevice:
         shots_dev = self.MinimalDevice(shots=100)
         assert shots_dev.shots == qml.measurements.Shots(100)
 
-        with pytest.raises(AttributeError):
+        with pytest.raises(
+            AttributeError, match="Shots can no longer be set on a device instance."
+        ):
             self.dev.shots = 100  # pylint: disable=attribute-defined-outside-init
 
+    def test_getattr_error(self):
+        """Test that querying a property that doesn't exist informs about interface change."""
+
+        with pytest.raises(
+            AttributeError,
+            match=r"You may be looking for a property or method present in the legacy device",
+        ):
+            _ = self.dev.expand_fn
+
     def test_tracker_set_on_initialization(self):
         """Test that a new tracker instance is initialized with the class."""
         assert isinstance(self.dev.tracker, qml.Tracker)
diff --git a/tests/devices/test_default_mixed_jax.py b/tests/devices/test_default_mixed_jax.py
index 466b73915..09869162e 100644
--- a/tests/devices/test_default_mixed_jax.py
+++ b/tests/devices/test_default_mixed_jax.py
@@ -28,7 +28,6 @@ pytestmark = pytest.mark.jax
 
 jax = pytest.importorskip("jax")
 jnp = pytest.importorskip("jax.numpy")
-config = pytest.importorskip("jax.config")
 
 
 decorators = [lambda x: x, jax.jit]
@@ -222,7 +221,7 @@ class TestDtypePreserved:
     def test_real_dtype(self, enable_x64, r_dtype, measurement):
         """Test that the user-defined dtype of the device is preserved
         for QNodes with real-valued outputs"""
-        config.config.update("jax_enable_x64", enable_x64)
+        jax.config.update("jax_enable_x64", enable_x64)
         p = jnp.array(0.543)
 
         dev = qml.device("default.mixed", wires=3, r_dtype=r_dtype)
@@ -243,7 +242,7 @@ class TestDtypePreserved:
     def test_complex_dtype(self, enable_x64, c_dtype, measurement):
         """Test that the user-defined dtype of the device is preserved
         for QNodes with complex-valued outputs"""
-        config.config.update("jax_enable_x64", enable_x64)
+        jax.config.update("jax_enable_x64", enable_x64)
         p = jnp.array(0.543)
 
         dev = qml.device("default.mixed", wires=3, c_dtype=c_dtype)
@@ -498,7 +497,7 @@ class TestPassthruIntegration:
     def test_state_differentiability(self, decorator, op, wire_ids, exp_fn, tol):
         """Test that the device state can be differentiated"""
         # pylint: disable=too-many-arguments
-        config.config.update("jax_enable_x64", True)
+        jax.config.update("jax_enable_x64", True)
 
         dev = qml.device("default.mixed", wires=1)
 
@@ -684,7 +683,7 @@ class TestPassthruIntegration:
         """Tests that the gradient of an arbitrary U3 gate is correct
         using the JAX interface, using a variety of differentiation methods."""
         if diff_method == "finite-diff":
-            config.config.update("jax_enable_x64", True)
+            jax.config.update("jax_enable_x64", True)
 
         dev = qml.device("default.mixed", wires=1)
         state = jnp.array(1j * np.array([1, -1]) / np.sqrt(2))
@@ -747,7 +746,7 @@ class TestPassthruIntegration:
         with prob and expval outputs"""
 
         if diff_method == "finite-diff":
-            config.config.update("jax_enable_x64", True)
+            jax.config.update("jax_enable_x64", True)
 
         dev = qml.device(dev_name, wires=2)
         x = jnp.array(0.543)
diff --git a/tests/devices/test_default_qutrit_mixed.py b/tests/devices/test_default_qutrit_mixed.py
index 197a97c9c..b58cd9ddf 100644
--- a/tests/devices/test_default_qutrit_mixed.py
+++ b/tests/devices/test_default_qutrit_mixed.py
@@ -1059,9 +1059,9 @@ class TestPRNGKeySeed:
 
     def test_prng_key_as_seed(self):
         """Test that a jax PRNG can be passed as a seed."""
-        from jax.config import config
+        import jax
 
-        config.update("jax_enable_x64", True)
+        jax.config.update("jax_enable_x64", True)
 
         from jax import random
 
diff --git a/tests/devices/test_preprocess.py b/tests/devices/test_preprocess.py
index dd677cdf8..0931a8d99 100644
--- a/tests/devices/test_preprocess.py
+++ b/tests/devices/test_preprocess.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 """Unit tests for preprocess in devices/qubit."""
+import warnings
 
 import pytest
 
@@ -137,10 +138,18 @@ def test_no_sampling():
 
 def test_validate_adjoint_trainable_params_obs_warning():
     """Tests warning raised for validate_adjoint_trainable_params with trainable observables."""
-    tape = qml.tape.QuantumScript([], [qml.expval(2 * qml.PauliX(0))])
+
+    params = qml.numpy.array(0.123)
+    tape = qml.tape.QuantumScript([], [qml.expval(2 * qml.RX(params, wires=0))])
     with pytest.warns(UserWarning, match="Differentiating with respect to the input "):
         validate_adjoint_trainable_params(tape)
 
+    params_non_trainable = qml.numpy.array(0.123, requires_grad=False)
+    tape = qml.tape.QuantumScript([], [qml.expval(2 * qml.RX(params_non_trainable, wires=0))])
+    with warnings.catch_warnings():
+        warnings.simplefilter("error")  # assert no warning raised
+        validate_adjoint_trainable_params(tape)
+
 
 def test_validate_adjoint_trainable_params_state_prep_error():
     """Tests error raised for validate_adjoint_trainable_params with trainable state-preps."""
diff --git a/tests/gradients/core/test_metric_tensor.py b/tests/gradients/core/test_metric_tensor.py
index 3f0cd8a77..bd2340627 100644
--- a/tests/gradients/core/test_metric_tensor.py
+++ b/tests/gradients/core/test_metric_tensor.py
@@ -1146,10 +1146,10 @@ class TestFullMetricTensor:
     @pytest.mark.parametrize("ansatz, params", zip(fubini_ansatze, fubini_params))
     @pytest.mark.parametrize("interface", ["auto", "jax"])
     def test_correct_output_jax(self, ansatz, params, interface):
-        from jax import config
+        import jax
         from jax import numpy as jnp
 
-        config.update("jax_enable_x64", True)
+        jax.config.update("jax_enable_x64", True)
 
         expected = autodiff_metric_tensor(ansatz, self.num_wires)(*params)
         dev = qml.device("default.qubit.jax", wires=self.num_wires + 1)
diff --git a/tests/interfaces/default_qubit_2_integration/test_jax_default_qubit_2.py b/tests/interfaces/default_qubit_2_integration/test_jax_default_qubit_2.py
index 7fae36f83..519c0daa0 100644
--- a/tests/interfaces/default_qubit_2_integration/test_jax_default_qubit_2.py
+++ b/tests/interfaces/default_qubit_2_integration/test_jax_default_qubit_2.py
@@ -24,8 +24,7 @@ from pennylane.measurements import Shots
 
 jax = pytest.importorskip("jax")
 jnp = pytest.importorskip("jax.numpy")
-config = pytest.importorskip("jax.config")
-config.config.update("jax_enable_x64", True)
+jax.config.update("jax_enable_x64", True)
 
 pytestmark = pytest.mark.jax
 
diff --git a/tests/interfaces/default_qubit_2_integration/test_jax_jit_qnode_default_qubit_2.py b/tests/interfaces/default_qubit_2_integration/test_jax_jit_qnode_default_qubit_2.py
index 7f96df420..cb1306d7b 100644
--- a/tests/interfaces/default_qubit_2_integration/test_jax_jit_qnode_default_qubit_2.py
+++ b/tests/interfaces/default_qubit_2_integration/test_jax_jit_qnode_default_qubit_2.py
@@ -47,8 +47,7 @@ interface_and_qubit_device_and_diff_method = [
 pytestmark = pytest.mark.jax
 
 jax = pytest.importorskip("jax")
-config = pytest.importorskip("jax.config")
-config.config.update("jax_enable_x64", True)
+jax.config.update("jax_enable_x64", True)
 
 TOL_FOR_SPSA = 1.0
 SEED_FOR_SPSA = 32651
diff --git a/tests/interfaces/default_qubit_2_integration/test_jax_qnode_default_qubit_2.py b/tests/interfaces/default_qubit_2_integration/test_jax_qnode_default_qubit_2.py
index b99bd7a08..46f0dc77e 100644
--- a/tests/interfaces/default_qubit_2_integration/test_jax_qnode_default_qubit_2.py
+++ b/tests/interfaces/default_qubit_2_integration/test_jax_qnode_default_qubit_2.py
@@ -50,8 +50,7 @@ interface_and_device_and_diff_method = [
 pytestmark = pytest.mark.jax
 
 jax = pytest.importorskip("jax")
-config = pytest.importorskip("jax.config")
-config.config.update("jax_enable_x64", True)
+jax.config.update("jax_enable_x64", True)
 
 TOL_FOR_SPSA = 1.0
 SEED_FOR_SPSA = 32651
diff --git a/tests/interfaces/test_jax_jit_qnode.py b/tests/interfaces/test_jax_jit_qnode.py
index 3c0ff4658..2cd5c3c56 100644
--- a/tests/interfaces/test_jax_jit_qnode.py
+++ b/tests/interfaces/test_jax_jit_qnode.py
@@ -35,8 +35,7 @@ interface_and_qubit_device_and_diff_method = [
 pytestmark = pytest.mark.jax
 
 jax = pytest.importorskip("jax")
-config = pytest.importorskip("jax.config")
-config.config.update("jax_enable_x64", True)
+jax.config.update("jax_enable_x64", True)
 
 TOL_FOR_SPSA = 1.0
 SEED_FOR_SPSA = 32651
diff --git a/tests/interfaces/test_jax_qnode.py b/tests/interfaces/test_jax_qnode.py
index 9b3896999..0803ff10e 100644
--- a/tests/interfaces/test_jax_qnode.py
+++ b/tests/interfaces/test_jax_qnode.py
@@ -38,8 +38,7 @@ interface_and_qubit_device_and_diff_method = [
 pytestmark = pytest.mark.jax
 
 jax = pytest.importorskip("jax")
-config = pytest.importorskip("jax.config")
-config.config.update("jax_enable_x64", True)
+jax.config.update("jax_enable_x64", True)
 
 TOL_FOR_SPSA = 1.0
 SEED_FOR_SPSA = 32651
diff --git a/tests/interfaces/test_jax_qnode_shot_vector.py b/tests/interfaces/test_jax_qnode_shot_vector.py
index 6645e008c..6530d3a05 100644
--- a/tests/interfaces/test_jax_qnode_shot_vector.py
+++ b/tests/interfaces/test_jax_qnode_shot_vector.py
@@ -23,8 +23,7 @@ from pennylane import qnode
 pytestmark = pytest.mark.jax
 
 jax = pytest.importorskip("jax")
-config = pytest.importorskip("jax.config")
-config.config.update("jax_enable_x64", True)
+jax.config.update("jax_enable_x64", True)
 
 all_shots = [(1, 20, 100), (1, (20, 1), 100), (1, (5, 4), 100)]
 
diff --git a/tests/ops/functions/conftest.py b/tests/ops/functions/conftest.py
index 80a9c0341..315cc3e50 100644
--- a/tests/ops/functions/conftest.py
+++ b/tests/ops/functions/conftest.py
@@ -24,7 +24,6 @@ import pytest
 import pennylane as qml
 from pennylane.operation import (
     Channel,
-    DiagGatesUndefinedError,
     MatrixUndefinedError,
     Observable,
     Operation,
@@ -61,6 +60,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."""
 
@@ -86,10 +86,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/functions/test_dot.py b/tests/ops/functions/test_dot.py
index d6157bfd4..53055442b 100644
--- a/tests/ops/functions/test_dot.py
+++ b/tests/ops/functions/test_dot.py
@@ -50,6 +50,11 @@ H3 = 1.0 * X0 + 2.0 * Y0 + 3.0 * Z0
 class TestDotSum:
     """Unittests for the dot function when ``pauli=False``."""
 
+    def test_error_if_ops_operator(self):
+        """Test that dot raises an error if ops is an operator itself."""
+        with pytest.raises(ValueError, match=r"ops must be an Iterable of Operator's"):
+            qml.dot([1, 1], qml.X(0) @ qml.Y(1))
+
     def test_dot_returns_sum(self):
         """Test that the dot function returns a Sum operator when ``pauli=False``."""
         c = [1.0, 2.0, 3.0]
@@ -280,6 +285,20 @@ ops0 = [
 class TestDotPauliSentence:
     """Unittest for the dot function when ``pauli=True``"""
 
+    def test_error_if_ops_PauliWord(self):
+        """Test that dot raises an error if ops is a PauliWord itself."""
+        _pw = qml.pauli.PauliWord({0: "X", 1: "Y"})
+        with pytest.raises(ValueError, match=r"ops must be an Iterable of PauliWord's"):
+            qml.dot([1, 2], _pw)
+
+    def test_error_if_ops_PauliSentence(self):
+        """Test that dot raises an error if ops is a PauliSentence itself."""
+        _pw1 = qml.pauli.PauliWord({0: "X", 1: "Y"})
+        _pw2 = qml.pauli.PauliWord({2: "Z"})
+        ps = 2 * _pw1 + 3 * _pw2
+        with pytest.raises(ValueError, match=r"ops must be an Iterable of PauliSentence's"):
+            qml.dot([1, 2], ps)
+
     def test_dot_returns_pauli_sentence(self):
         """Test that the dot function returns a PauliSentence class."""
         ps = qml.dot(coeffs0, ops0, pauli=True)
diff --git a/tests/ops/op_math/test_linear_combination.py b/tests/ops/op_math/test_linear_combination.py
index e2b71772c..74e8ec64c 100644
--- a/tests/ops/op_math/test_linear_combination.py
+++ b/tests/ops/op_math/test_linear_combination.py
@@ -564,6 +564,12 @@ dev = qml.device("default.qubit", wires=2)
 class TestLinearCombination:
     """Test the LinearCombination class"""
 
+    def test_error_if_observables_operator(self):
+        """Test thatt an error is raised if an operator is provided to observables."""
+
+        with pytest.raises(ValueError, match=r"observables must be an Iterable of Operator's"):
+            qml.ops.LinearCombination([1, 1], qml.X(0) @ qml.Y(1))
+
     PAULI_REPS = (
         ([], [], PauliSentence({})),
         (
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)