Repository: PennyLaneAI/pennylane
Pull request #5925 (2024-07-02 02:51:20)

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/5925?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.66%. Comparing base [(`e74c9bf`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/commit/e74c9bf821518196ce3bc1c8a740d63179cef9c3?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) to head [(`9653024`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/commit/96530241eb26a8f624a86d464743a9b24c631a4e?dropdown=coverage&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    #5925      +/-   ##
==========================================
- Coverage   99.67%   99.66%   -0.01%     
==========================================
  Files         425      425              
  Lines       40772    40477     -295     
==========================================
- Hits        40640    40343     -297     
- Misses        132      134       +2     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5925?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/development/deprecations.rst b/doc/development/deprecations.rst
index 23f2c0749..97ef6cb6e 100644
--- a/doc/development/deprecations.rst
+++ b/doc/development/deprecations.rst
@@ -22,9 +22,9 @@ Pending deprecations
   - Will be removed in v0.38
 
 * ``qml.from_qasm`` will no longer remove measurements from the QASM code. Calling ``qml.from_qasm``
-  without specifying ``measurements`` will raise a deprecation warning in v0.37, and in v0.38,
-  the default behaviour will be changed to keeping measurements. Use ``measurements=[]`` to remove
-  measurements from the original circuit.
+  on a circuit containing measurements without specifying ``measurements`` will raise a deprecation 
+  warning in v0.37, and in v0.38, the default behaviour will be changed to keeping measurements. Use 
+  ``measurements=[]`` to remove measurements from the original circuit.
 
   - Deprecated in v0.37
   - Default behaviour will be changed in v0.38
diff --git a/doc/releases/changelog-0.37.0.md b/doc/releases/changelog-0.37.0.md
index eaa2edfd2..4f6f1d7a2 100644
--- a/doc/releases/changelog-0.37.0.md
+++ b/doc/releases/changelog-0.37.0.md
@@ -306,7 +306,6 @@
 * The `qml.data` module now supports PyTree data types as dataset attributes
   [(#5732)](https://github.com/PennyLaneAI/pennylane/pull/5732)
 
-
 * `qml.ops.Conditional` now inherits from `qml.ops.SymbolicOp`, thus it inherits several useful common functionalities. Other properties such as adjoint and diagonalizing gates have been added using the `base` properties.
   [(##5772)](https://github.com/PennyLaneAI/pennylane/pull/5772)
 
@@ -416,6 +415,7 @@
 
 * The default behaviour of `qml.from_qasm()` to remove measurements in the QASM code is deprecated. Use `measurements=[]` to keep this behaviour or `measurements=None` to keep the measurements from the QASM code.
   [(#5882)](https://github.com/PennyLaneAI/pennylane/pull/5882)
+  [(#5904)](https://github.com/PennyLaneAI/pennylane/pull/5904)
 
 <h3>Documentation 📝</h3>
 
@@ -443,6 +443,9 @@
 
 <h3>Bug fixes 🐛</h3>
 
+* The `default.tensor` device now preserves the order of wires if the initial MPS is created from a dense state vector.
+  [(#5892)](https://github.com/PennyLaneAI/pennylane/pull/5892)
+
 * Fixes a bug where `hadamard_grad` returned a wrong shape for `qml.probs()` without wires.
   [(#5860)](https://github.com/PennyLaneAI/pennylane/pull/5860)
 
diff --git a/pennylane/devices/default_tensor.py b/pennylane/devices/default_tensor.py
index d16a4c140..2ebf0e31f 100644
--- a/pennylane/devices/default_tensor.py
+++ b/pennylane/devices/default_tensor.py
@@ -669,13 +669,19 @@ class DefaultTensor(Device):
             self._quimb_circuit = self._initial_quimb_circuit(
                 wires,
                 psi0=self._initial_mps(
-                    op.wires, basis_state="".join(str(int(b)) for b in op.parameters[0])
+                    op.wires,
+                    basis_state="".join(
+                        str(int(b)) for b in op.parameters[0].astype(self._c_dtype)
+                    ),
                 ),
             )
         elif operations and isinstance(operations[0], qml.StatePrep):
             op = operations.pop(0)
             self._quimb_circuit = self._initial_quimb_circuit(
-                wires, psi0=qtn.MatrixProductState.from_dense(op.state_vector())
+                wires,
+                psi0=qtn.MatrixProductState.from_dense(
+                    op.state_vector(wire_order=wires).astype(self._c_dtype)
+                ),
             )
         else:
             self._quimb_circuit = self._initial_quimb_circuit(wires)
diff --git a/pennylane/io.py b/pennylane/io.py
index 444655212..3416f9b9b 100644
--- a/pennylane/io.py
+++ b/pennylane/io.py
@@ -505,14 +505,15 @@ def from_qasm(quantum_circuit: str, measurements=False):
     """
     plugin_converter = plugin_converters["qasm"].load()
     if measurements is False:
-        warnings.warn(
-            "The current default behaviour of removing measurements in the QASM code is "
-            "deprecated. Set measurements=None to keep the existing measurements in the QASM "
-            "code or set measurements=[] to remove them from the returned circuit. Starting "
-            "in version 0.38, measurements=None will be the new default.",
-            qml.PennyLaneDeprecationWarning,
-        )
         measurements = []
+        if "measure" in quantum_circuit:
+            warnings.warn(
+                "The current default behaviour of removing measurements in the QASM code "
+                "is deprecated. Set measurements=None to keep existing measurements in the QASM "
+                "code or set measurements=[] to remove them from the returned circuit. Starting "
+                "in version 0.38, measurements=None will be the new default.",
+                qml.PennyLaneDeprecationWarning,
+            )
     return plugin_converter(quantum_circuit, measurements=measurements)
 
 


Test patch:
diff --git a/tests/devices/default_tensor/test_default_tensor.py b/tests/devices/default_tensor/test_default_tensor.py
index 3bebce931..056af1291 100644
--- a/tests/devices/default_tensor/test_default_tensor.py
+++ b/tests/devices/default_tensor/test_default_tensor.py
@@ -16,11 +16,16 @@ Unit tests for the DefaultTensor class.
 """
 
 
+import math
+
 import numpy as np
 import pytest
+from scipy.linalg import expm
 from scipy.sparse import csr_matrix
 
 import pennylane as qml
+from pennylane.qchem import givens_decomposition
+from pennylane.typing import TensorLike
 from pennylane.wires import WireError
 
 quimb = pytest.importorskip("quimb")
@@ -414,3 +419,81 @@ class TestJaxSupport:
             return qml.expval(qml.Z(0))
 
         assert np.allclose(circuit(), 0.0)
+
+
+@pytest.mark.parametrize("method", ["mps", "tn"])
+@pytest.mark.parametrize(
+    "operation, expected_output, par",
+    [
+        (qml.BasisState, [0, 0, 1 + 0j, 0], [1 + 0j, 0]),
+        (qml.BasisState, [0, 0, 0, 1 + 0j], [1 + 0j, 1 + 0j]),
+        (qml.BasisState, [0, 0, 1, 0], [1, 0]),
+        (qml.BasisState, [0, 0, 0, 1], [1, 1]),
+        (qml.StatePrep, [0, 0, 1 + 0j, 0], [0, 0, 1 + 0j, 0]),
+        (qml.StatePrep, [0, 0, 0, 1 + 0j], [0, 0, 0, 1 + 0j]),
+        (qml.StatePrep, [0, 0, 1, 0], [0, 0, 1, 0]),
+        (qml.StatePrep, [0, 0, 0, 1], [0, 0, 0, 1]),
+        (
+            qml.StatePrep,
+            [1 / math.sqrt(3), 0, 1 / math.sqrt(3), 1 / math.sqrt(3)],
+            [1 / math.sqrt(3), 0, 1 / math.sqrt(3), 1 / math.sqrt(3)],
+        ),
+        (
+            qml.StatePrep,
+            [1 / math.sqrt(3), 0, -1 / math.sqrt(3), 1 / math.sqrt(3)],
+            [1 / math.sqrt(3), 0, -1 / math.sqrt(3), 1 / math.sqrt(3)],
+        ),
+    ],
+)
+def test_apply_operation_state_preparation(operation, expected_output, par, method):
+    """Tests that applying an operation yields the expected output state for single wire
+    operations that have no parameters."""
+
+    par = np.array(par)
+    dev = qml.device("default.tensor", method=method, wires=2)
+
+    @qml.qnode(dev)
+    def circuit():
+        operation(par, wires=[0, 1])
+        return qml.state()
+
+    state = circuit()
+    assert np.allclose(state, np.array(expected_output), rtol=0)
+
+
+# At this stage, this test is especially relevant for the MPS method, but we test both methods for consistency.
+@pytest.mark.parametrize("num_orbitals", [2, 4])
+@pytest.mark.parametrize("method", ["mps", "tn"])
+def test_wire_order_dense_vector(method, num_orbitals):
+    """Test that the wire order is preserved if the initial state is created from a dense vector."""
+
+    dev = qml.device("default.tensor", wires=int(2 * num_orbitals + 1), method=method)
+    qubits = dev.wires.tolist()
+
+    wave_fun = np.random.random((2 ** (2 * num_orbitals))) + 1j * np.random.random(
+        (2 ** (2 * num_orbitals))
+    )
+    wave_fun = wave_fun / np.linalg.norm(wave_fun)
+
+    X0 = np.random.random((num_orbitals, num_orbitals))
+    U0 = expm((X0 + X0.T) / 2.0)
+
+    def basis_rotation_ops(unitary_matrix, wires):
+        _, givens_list = givens_decomposition(unitary_matrix)
+
+        for grot_mat, indices in givens_list:
+            theta = np.arccos(np.real(grot_mat[1, 1]))
+            qml.SingleExcitation(2 * theta, wires=[int(wires[indices[0]]), int(wires[indices[1]])])
+
+    control_wires = 1
+
+    @qml.qnode(dev)
+    def circuit():
+        qml.StatePrep(wave_fun, wires=qubits[1:])
+        qml.Hadamard(qubits[0])
+        basis_rotation_ops(U0, [int(2 * i + 1 + control_wires) for i in range(num_orbitals)])
+        return qml.state()
+
+    state = circuit()
+    assert isinstance(state, TensorLike)
+    assert len(state) == 2 ** (2 * num_orbitals + 1)
diff --git a/tests/test_io.py b/tests/test_io.py
index d59b22ba8..fa3ed2dc6 100644
--- a/tests/test_io.py
+++ b/tests/test_io.py
@@ -137,7 +137,7 @@ class TestLoad:
     def test_from_qasm(self, mock_plugin_converters):
         """Tests that the correct entry point is called for from_qasm."""
 
-        qml.from_qasm("Test", measurements=None)
+        qml.from_qasm("Test")
         assert mock_plugin_converters["qasm"].called
         assert mock_plugin_converters["qasm"].last_args == ("Test",)
 
@@ -149,10 +149,10 @@ class TestLoad:
         """Tests that the current default behaviour of from_qasm is deprecated."""
 
         with pytest.warns(qml.PennyLaneDeprecationWarning, match="The current default behaviour"):
-            qml.from_qasm("Test")
+            qml.from_qasm("measure q[i] -> c[i];")
 
         called_args, called_kwargs = mock_plugin_converters["qasm"].call_args
-        assert called_args == ("Test",)
+        assert called_args == ("measure q[i] -> c[i];",)
         assert called_kwargs == {"measurements": []}
 
     @pytest.mark.parametrize(