We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[BUG] pennylane.tape.Unwarp does not unwrap Hamiltonian coefficients
### Expected behavior

`qml.tape.unwrap` convert all ArrayBox in a tape to usual arrays.

### Actual behavior

Coefficients of the `Hamiltonian` object instance (accessible via `ham.coeffs`) are not unwrapped.

### Additional information

_No response_

### Source code

_No response_

### Tracebacks

_No response_

### System information

```shell
Name: PennyLane
Version: 0.26.0.dev0
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: https://github.com/XanaduAI/pennylane
Author: 
Author-email: 
License: Apache License 2.0
Location: /home/chae-yeun/work/Xanadu/devel-py39/lib/python3.9/site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, retworkx, scipy, semantic-version, toml
Required-by: PennyLane-Lightning

Platform info:           Linux-5.14.0-1042-oem-x86_64-with-glibc2.35
Python version:          3.9.13
Numpy version:           1.23.2
Scipy version:           1.9.0
Installed devices:
- lightning.qubit (PennyLane-Lightning-0.26.0.dev1)
- default.gaussian (PennyLane-0.26.0.dev0)
- default.mixed (PennyLane-0.26.0.dev0)
- default.qubit (PennyLane-0.26.0.dev0)
- default.qubit.autograd (PennyLane-0.26.0.dev0)
- default.qubit.jax (PennyLane-0.26.0.dev0)
- default.qubit.tf (PennyLane-0.26.0.dev0)
- default.qubit.torch (PennyLane-0.26.0.dev0)
- default.qutrit (PennyLane-0.26.0.dev0)
```


### Existing GitHub issues

- [X] I have searched existing GitHub issues to make sure the issue does not already exist.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pennylane/transforms/convert_to_numpy_parameters.py`
Content:
```
1 # Copyright 2018-2023 Xanadu Quantum Technologies Inc.
2 
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """
15 This file contains preprocessings steps that may be called internally
16 during execution.
17 """
18 import copy
19 
20 import pennylane as qml
21 from pennylane import math
22 from pennylane.tape import QuantumScript
23 
24 
25 def _convert_op_to_numpy_data(op: qml.operation.Operator) -> qml.operation.Operator:
26     if math.get_interface(*op.data) == "numpy":
27         return op
28     # Use operator method to change parameters when it become available
29     copied_op = copy.copy(op)
30     copied_op.data = math.unwrap(op.data)
31     return copied_op
32 
33 
34 def _convert_measurement_to_numpy_data(
35     m: qml.measurements.MeasurementProcess,
36 ) -> qml.measurements.MeasurementProcess:
37     if m.obs is None or math.get_interface(*m.obs.data) == "numpy":
38         return m
39     # Use measurement method to change parameters when it becomes available
40     copied_m = copy.copy(m)
41     if isinstance(copied_m.obs, qml.operation.Tensor):
42         copied_m.obs.data = math.unwrap([o.data for o in m.obs.obs])
43     else:
44         copied_m.obs.data = math.unwrap(m.obs.data)
45     return copied_m
46 
47 
48 # pylint: disable=protected-access
49 def convert_to_numpy_parameters(circuit: QuantumScript) -> QuantumScript:
50     """Transforms a circuit to one with purely numpy parameters.
51 
52     Args:
53         circuit (QuantumScript): a circuit with parameters of any interface
54 
55     Returns:
56         QuantumScript: A circuit with purely numpy parameters
57 
58     .. seealso::
59 
60         :class:`pennylane.tape.Unwrap` modifies a :class:`~.pennylane.tape.QuantumScript` in place instead of creating
61         a new class. It will also set all parameters on the circuit, not just ones that need to be unwrapped.
62 
63     >>> ops = [qml.S(0), qml.RX(torch.tensor(0.1234), 0)]
64     >>> measurements = [qml.state(), qml.expval(qml.Hermitian(torch.eye(2), 0))]
65     >>> circuit = qml.tape.QuantumScript(ops, measurements )
66     >>> new_circuit = convert_to_numpy_parameters(circuit)
67     >>> new_circuit.circuit
68     [S(wires=[0]),
69     RX(0.1234000027179718, wires=[0]),
70     state(wires=[]),
71     expval(Hermitian(array([[1., 0.],
72             [0., 1.]], dtype=float32), wires=[0]))]
73 
74     If the component's data does not need to be transformed, it is left uncopied.
75 
76     >>> circuit[0] is new_circuit[0]
77     True
78     >>> circuit[1] is new_circuit[1]
79     False
80     >>> circuit[2] is new_circuit[2]
81     True
82     >>> circuit[3] is new_circuit[3]
83     False
84 
85     """
86     new_ops = (_convert_op_to_numpy_data(op) for op in circuit.operations)
87     new_measurements = (_convert_measurement_to_numpy_data(m) for m in circuit.measurements)
88     new_circuit = circuit.__class__(new_ops, new_measurements, shots=circuit.shots)
89     # must preserve trainable params as we lose information about the machine learning interface
90     new_circuit.trainable_params = circuit.trainable_params
91     new_circuit._qfunc_output = circuit._qfunc_output
92     return new_circuit
93
```

Path: `pennylane/ops/functions/bind_new_parameters.py`
Content:
```
1 # Copyright 2018-2023 Xanadu Quantum Technologies Inc.
2 
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """
15 This module contains the qml.bind_new_parameters function.
16 """
17 # pylint: disable=missing-docstring
18 
19 from typing import Sequence
20 import copy
21 from functools import singledispatch
22 
23 import pennylane as qml
24 from pennylane.typing import TensorLike
25 from pennylane.operation import Operator, Tensor
26 
27 from ..identity import Identity
28 from ..qubit import Projector
29 from ..op_math import CompositeOp, SymbolicOp, ScalarSymbolicOp, Adjoint, Pow, SProd
30 
31 
32 @singledispatch
33 def bind_new_parameters(op: Operator, params: Sequence[TensorLike]) -> Operator:
34     """Create a new operator with updated parameters
35 
36     This function takes an :class:`~.Operator` and new parameters as input and
37     returns a new operator of the same type with the new parameters. This function
38     does not mutate the original operator.
39 
40     Args:
41         op (.Operator): Operator to update
42         params (Sequence[TensorLike]): New parameters to create operator with. This
43             must have the same shape as `op.data`.
44 
45     Returns:
46         .Operator: New operator with updated parameters
47     """
48     try:
49         return op.__class__(*params, wires=op.wires, **copy.deepcopy(op.hyperparameters))
50     except TypeError:
51         # operation is doing something different with its call signature.
52         new_op = copy.deepcopy(op)
53         new_op.data = tuple(params)
54         return new_op
55 
56 
57 @bind_new_parameters.register
58 def bind_new_parameters_approx_time_evolution(
59     op: qml.ApproxTimeEvolution, params: Sequence[TensorLike]
60 ):
61     new_hamiltonian = bind_new_parameters(op.hyperparameters["hamiltonian"], params[:-1])
62     time = params[-1]
63     n = op.hyperparameters["n"]
64 
65     return qml.ApproxTimeEvolution(new_hamiltonian, time, n)
66 
67 
68 @bind_new_parameters.register
69 def bind_new_parameters_commuting_evolution(
70     op: qml.CommutingEvolution, params: Sequence[TensorLike]
71 ):
72     new_hamiltonian = bind_new_parameters(op.hyperparameters["hamiltonian"], params[1:])
73     freq = op.hyperparameters["frequencies"]
74     shifts = op.hyperparameters["shifts"]
75     time = params[0]
76 
77     return qml.CommutingEvolution(new_hamiltonian, time, frequencies=freq, shifts=shifts)
78 
79 
80 @bind_new_parameters.register
81 def bind_new_parameters_fermionic_double_excitation(
82     op: qml.FermionicDoubleExcitation, params: Sequence[TensorLike]
83 ):
84     wires1 = op.hyperparameters["wires1"]
85     wires2 = op.hyperparameters["wires2"]
86 
87     return qml.FermionicDoubleExcitation(params[0], wires1=wires1, wires2=wires2)
88 
89 
90 @bind_new_parameters.register
91 def bind_new_parameters_angle_embedding(op: qml.AngleEmbedding, params: Sequence[TensorLike]):
92     rotation = op.hyperparameters["rotation"].basis
93     return qml.AngleEmbedding(params[0], wires=op.wires, rotation=rotation)
94 
95 
96 @bind_new_parameters.register
97 def bind_new_parameters_identity(op: Identity, params: Sequence[TensorLike]):
98     return qml.Identity(*params, wires=op.wires)
99 
100 
101 @bind_new_parameters.register
102 def bind_new_parameters_composite_op(op: CompositeOp, params: Sequence[TensorLike]):
103     new_operands = []
104 
105     for operand in op.operands:
106         op_num_params = operand.num_params
107         sub_params = params[:op_num_params]
108         params = params[op_num_params:]
109         new_operands.append(bind_new_parameters(operand, sub_params))
110 
111     return op.__class__(*new_operands)
112 
113 
114 @bind_new_parameters.register
115 def bind_new_parameters_symbolic_op(op: SymbolicOp, params: Sequence[TensorLike]):
116     new_base = bind_new_parameters(op.base, params)
117     new_hyperparameters = copy.deepcopy(op.hyperparameters)
118     _ = new_hyperparameters.pop("base")
119 
120     return op.__class__(new_base, **new_hyperparameters)
121 
122 
123 @bind_new_parameters.register
124 def bind_new_parameters_adjoint(op: Adjoint, params: Sequence[TensorLike]):
125     # Need a separate dispatch for `Adjoint` because using a more general class
126     # signature results in a call to `Adjoint.__new__` which doesn't raise an
127     # error but does return an unusable object.
128     return Adjoint(bind_new_parameters(op.base, params))
129 
130 
131 @bind_new_parameters.register
132 def bind_new_parameters_projector(op: Projector, params: Sequence[TensorLike]):
133     # Need a separate dispatch for `Projector` because using a more general class
134     # signature results in a call to `Projector.__new__` which doesn't raise an
135     # error but does return an unusable object.
136     return Projector(*params, wires=op.wires)
137 
138 
139 @bind_new_parameters.register
140 def bind_new_parameters_scalar_symbolic_op(op: ScalarSymbolicOp, params: Sequence[TensorLike]):
141     new_scalar = params[0]
142     params = params[1:]
143 
144     new_base = bind_new_parameters(op.base, params)
145     new_hyperparameters = copy.deepcopy(op.hyperparameters)
146     _ = new_hyperparameters.pop("base")
147 
148     return op.__class__(new_base, new_scalar, **new_hyperparameters)
149 
150 
151 @bind_new_parameters.register
152 def bind_new_parameters_sprod(op: SProd, params: Sequence[TensorLike]):
153     # Separate dispatch for `SProd` since its constructor has a different interface
154     new_scalar = params[0]
155     params = params[1:]
156     new_base = bind_new_parameters(op.base, params)
157 
158     return SProd(new_scalar, new_base)
159 
160 
161 @bind_new_parameters.register
162 def bind_new_parameters_pow(op: Pow, params: Sequence[TensorLike]):
163     # Need a separate dispatch for `Pow` because using a more general class
164     # signature results in a call to `Pow.__new__` which doesn't raise an
165     # error but does return an unusable object.
166     return Pow(bind_new_parameters(op.base, params), op.scalar)
167 
168 
169 @bind_new_parameters.register
170 def bind_new_parameters_hamiltonian(op: qml.Hamiltonian, params: Sequence[TensorLike]):
171     return qml.Hamiltonian(params, op.ops)
172 
173 
174 @bind_new_parameters.register
175 def bind_new_parameters_tensor(op: Tensor, params: Sequence[TensorLike]):
176     new_obs = []
177 
178     for obs in op.obs:
179         sub_params = params[: obs.num_params]
180         params = params[obs.num_params :]
181         new_obs.append(bind_new_parameters(obs, sub_params))
182 
183     return Tensor(*new_obs)
184
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pennylane/ops/functions/bind_new_parameters.py b/pennylane/ops/functions/bind_new_parameters.py
--- a/pennylane/ops/functions/bind_new_parameters.py
+++ b/pennylane/ops/functions/bind_new_parameters.py
@@ -47,7 +47,7 @@
     """
     try:
         return op.__class__(*params, wires=op.wires, **copy.deepcopy(op.hyperparameters))
-    except TypeError:
+    except (TypeError, ValueError):
         # operation is doing something different with its call signature.
         new_op = copy.deepcopy(op)
         new_op.data = tuple(params)
@@ -168,7 +168,10 @@
 
 @bind_new_parameters.register
 def bind_new_parameters_hamiltonian(op: qml.Hamiltonian, params: Sequence[TensorLike]):
-    return qml.Hamiltonian(params, op.ops)
+    new_H = qml.Hamiltonian(params, op.ops)
+    if op.grouping_indices is not None:
+        new_H.grouping_indices = op.grouping_indices
+    return new_H
 
 
 @bind_new_parameters.register
diff --git a/pennylane/transforms/convert_to_numpy_parameters.py b/pennylane/transforms/convert_to_numpy_parameters.py
--- a/pennylane/transforms/convert_to_numpy_parameters.py
+++ b/pennylane/transforms/convert_to_numpy_parameters.py
@@ -15,34 +15,32 @@
 This file contains preprocessings steps that may be called internally
 during execution.
 """
-import copy
-
 import pennylane as qml
 from pennylane import math
 from pennylane.tape import QuantumScript
 
 
+# pylint: disable=no-member
 def _convert_op_to_numpy_data(op: qml.operation.Operator) -> qml.operation.Operator:
     if math.get_interface(*op.data) == "numpy":
         return op
     # Use operator method to change parameters when it become available
-    copied_op = copy.copy(op)
-    copied_op.data = math.unwrap(op.data)
-    return copied_op
+    return qml.ops.functions.bind_new_parameters(op, math.unwrap(op.data))
 
 
+# pylint: disable=no-member
 def _convert_measurement_to_numpy_data(
     m: qml.measurements.MeasurementProcess,
 ) -> qml.measurements.MeasurementProcess:
-    if m.obs is None or math.get_interface(*m.obs.data) == "numpy":
+    if m.obs is None:
+        if m.eigvals() is None or math.get_interface(m.eigvals()) == "numpy":
+            return m
+        return type(m)(wires=m.wires, eigvals=math.unwrap(m.eigvals()))
+
+    if math.get_interface(*m.obs.data) == "numpy":
         return m
-    # Use measurement method to change parameters when it becomes available
-    copied_m = copy.copy(m)
-    if isinstance(copied_m.obs, qml.operation.Tensor):
-        copied_m.obs.data = math.unwrap([o.data for o in m.obs.obs])
-    else:
-        copied_m.obs.data = math.unwrap(m.obs.data)
-    return copied_m
+    new_obs = qml.ops.functions.bind_new_parameters(m.obs, math.unwrap(m.obs.data))
+    return type(m)(obs=new_obs)
 
 
 # pylint: disable=protected-access

{"golden_diff": "diff --git a/pennylane/ops/functions/bind_new_parameters.py b/pennylane/ops/functions/bind_new_parameters.py\n--- a/pennylane/ops/functions/bind_new_parameters.py\n+++ b/pennylane/ops/functions/bind_new_parameters.py\n@@ -47,7 +47,7 @@\n     \"\"\"\n     try:\n         return op.__class__(*params, wires=op.wires, **copy.deepcopy(op.hyperparameters))\n-    except TypeError:\n+    except (TypeError, ValueError):\n         # operation is doing something different with its call signature.\n         new_op = copy.deepcopy(op)\n         new_op.data = tuple(params)\n@@ -168,7 +168,10 @@\n \n @bind_new_parameters.register\n def bind_new_parameters_hamiltonian(op: qml.Hamiltonian, params: Sequence[TensorLike]):\n-    return qml.Hamiltonian(params, op.ops)\n+    new_H = qml.Hamiltonian(params, op.ops)\n+    if op.grouping_indices is not None:\n+        new_H.grouping_indices = op.grouping_indices\n+    return new_H\n \n \n @bind_new_parameters.register\ndiff --git a/pennylane/transforms/convert_to_numpy_parameters.py b/pennylane/transforms/convert_to_numpy_parameters.py\n--- a/pennylane/transforms/convert_to_numpy_parameters.py\n+++ b/pennylane/transforms/convert_to_numpy_parameters.py\n@@ -15,34 +15,32 @@\n This file contains preprocessings steps that may be called internally\n during execution.\n \"\"\"\n-import copy\n-\n import pennylane as qml\n from pennylane import math\n from pennylane.tape import QuantumScript\n \n \n+# pylint: disable=no-member\n def _convert_op_to_numpy_data(op: qml.operation.Operator) -> qml.operation.Operator:\n     if math.get_interface(*op.data) == \"numpy\":\n         return op\n     # Use operator method to change parameters when it become available\n-    copied_op = copy.copy(op)\n-    copied_op.data = math.unwrap(op.data)\n-    return copied_op\n+    return qml.ops.functions.bind_new_parameters(op, math.unwrap(op.data))\n \n \n+# pylint: disable=no-member\n def _convert_measurement_to_numpy_data(\n     m: qml.measurements.MeasurementProcess,\n ) -> qml.measurements.MeasurementProcess:\n-    if m.obs is None or math.get_interface(*m.obs.data) == \"numpy\":\n+    if m.obs is None:\n+        if m.eigvals() is None or math.get_interface(m.eigvals()) == \"numpy\":\n+            return m\n+        return type(m)(wires=m.wires, eigvals=math.unwrap(m.eigvals()))\n+\n+    if math.get_interface(*m.obs.data) == \"numpy\":\n         return m\n-    # Use measurement method to change parameters when it becomes available\n-    copied_m = copy.copy(m)\n-    if isinstance(copied_m.obs, qml.operation.Tensor):\n-        copied_m.obs.data = math.unwrap([o.data for o in m.obs.obs])\n-    else:\n-        copied_m.obs.data = math.unwrap(m.obs.data)\n-    return copied_m\n+    new_obs = qml.ops.functions.bind_new_parameters(m.obs, math.unwrap(m.obs.data))\n+    return type(m)(obs=new_obs)\n \n \n # pylint: disable=protected-access\n", "issue": "[BUG] pennylane.tape.Unwarp does not unwrap Hamiltonian coefficients\n### Expected behavior\r\n\r\n`qml.tape.unwrap` convert all ArrayBox in a tape to usual arrays.\r\n\r\n### Actual behavior\r\n\r\nCoefficients of the `Hamiltonian` object instance (accessible via `ham.coeffs`) are not unwrapped.\r\n\r\n### Additional information\r\n\r\n_No response_\r\n\r\n### Source code\r\n\r\n_No response_\r\n\r\n### Tracebacks\r\n\r\n_No response_\r\n\r\n### System information\r\n\r\n```shell\r\nName: PennyLane\r\nVersion: 0.26.0.dev0\r\nSummary: PennyLane is a Python quantum machine learning library by Xanadu Inc.\r\nHome-page: https://github.com/XanaduAI/pennylane\r\nAuthor: \r\nAuthor-email: \r\nLicense: Apache License 2.0\r\nLocation: /home/chae-yeun/work/Xanadu/devel-py39/lib/python3.9/site-packages\r\nRequires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, retworkx, scipy, semantic-version, toml\r\nRequired-by: PennyLane-Lightning\r\n\r\nPlatform info:           Linux-5.14.0-1042-oem-x86_64-with-glibc2.35\r\nPython version:          3.9.13\r\nNumpy version:           1.23.2\r\nScipy version:           1.9.0\r\nInstalled devices:\r\n- lightning.qubit (PennyLane-Lightning-0.26.0.dev1)\r\n- default.gaussian (PennyLane-0.26.0.dev0)\r\n- default.mixed (PennyLane-0.26.0.dev0)\r\n- default.qubit (PennyLane-0.26.0.dev0)\r\n- default.qubit.autograd (PennyLane-0.26.0.dev0)\r\n- default.qubit.jax (PennyLane-0.26.0.dev0)\r\n- default.qubit.tf (PennyLane-0.26.0.dev0)\r\n- default.qubit.torch (PennyLane-0.26.0.dev0)\r\n- default.qutrit (PennyLane-0.26.0.dev0)\r\n```\r\n\r\n\r\n### Existing GitHub issues\r\n\r\n- [X] I have searched existing GitHub issues to make sure the issue does not already exist.\n", "before_files": [{"content": "# Copyright 2018-2023 Xanadu Quantum Technologies Inc.\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n\n#     http://www.apache.org/licenses/LICENSE-2.0\n\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis file contains preprocessings steps that may be called internally\nduring execution.\n\"\"\"\nimport copy\n\nimport pennylane as qml\nfrom pennylane import math\nfrom pennylane.tape import QuantumScript\n\n\ndef _convert_op_to_numpy_data(op: qml.operation.Operator) -> qml.operation.Operator:\n    if math.get_interface(*op.data) == \"numpy\":\n        return op\n    # Use operator method to change parameters when it become available\n    copied_op = copy.copy(op)\n    copied_op.data = math.unwrap(op.data)\n    return copied_op\n\n\ndef _convert_measurement_to_numpy_data(\n    m: qml.measurements.MeasurementProcess,\n) -> qml.measurements.MeasurementProcess:\n    if m.obs is None or math.get_interface(*m.obs.data) == \"numpy\":\n        return m\n    # Use measurement method to change parameters when it becomes available\n    copied_m = copy.copy(m)\n    if isinstance(copied_m.obs, qml.operation.Tensor):\n        copied_m.obs.data = math.unwrap([o.data for o in m.obs.obs])\n    else:\n        copied_m.obs.data = math.unwrap(m.obs.data)\n    return copied_m\n\n\n# pylint: disable=protected-access\ndef convert_to_numpy_parameters(circuit: QuantumScript) -> QuantumScript:\n    \"\"\"Transforms a circuit to one with purely numpy parameters.\n\n    Args:\n        circuit (QuantumScript): a circuit with parameters of any interface\n\n    Returns:\n        QuantumScript: A circuit with purely numpy parameters\n\n    .. seealso::\n\n        :class:`pennylane.tape.Unwrap` modifies a :class:`~.pennylane.tape.QuantumScript` in place instead of creating\n        a new class. It will also set all parameters on the circuit, not just ones that need to be unwrapped.\n\n    >>> ops = [qml.S(0), qml.RX(torch.tensor(0.1234), 0)]\n    >>> measurements = [qml.state(), qml.expval(qml.Hermitian(torch.eye(2), 0))]\n    >>> circuit = qml.tape.QuantumScript(ops, measurements )\n    >>> new_circuit = convert_to_numpy_parameters(circuit)\n    >>> new_circuit.circuit\n    [S(wires=[0]),\n    RX(0.1234000027179718, wires=[0]),\n    state(wires=[]),\n    expval(Hermitian(array([[1., 0.],\n            [0., 1.]], dtype=float32), wires=[0]))]\n\n    If the component's data does not need to be transformed, it is left uncopied.\n\n    >>> circuit[0] is new_circuit[0]\n    True\n    >>> circuit[1] is new_circuit[1]\n    False\n    >>> circuit[2] is new_circuit[2]\n    True\n    >>> circuit[3] is new_circuit[3]\n    False\n\n    \"\"\"\n    new_ops = (_convert_op_to_numpy_data(op) for op in circuit.operations)\n    new_measurements = (_convert_measurement_to_numpy_data(m) for m in circuit.measurements)\n    new_circuit = circuit.__class__(new_ops, new_measurements, shots=circuit.shots)\n    # must preserve trainable params as we lose information about the machine learning interface\n    new_circuit.trainable_params = circuit.trainable_params\n    new_circuit._qfunc_output = circuit._qfunc_output\n    return new_circuit\n", "path": "pennylane/transforms/convert_to_numpy_parameters.py"}, {"content": "# Copyright 2018-2023 Xanadu Quantum Technologies Inc.\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n\n#     http://www.apache.org/licenses/LICENSE-2.0\n\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis module contains the qml.bind_new_parameters function.\n\"\"\"\n# pylint: disable=missing-docstring\n\nfrom typing import Sequence\nimport copy\nfrom functools import singledispatch\n\nimport pennylane as qml\nfrom pennylane.typing import TensorLike\nfrom pennylane.operation import Operator, Tensor\n\nfrom ..identity import Identity\nfrom ..qubit import Projector\nfrom ..op_math import CompositeOp, SymbolicOp, ScalarSymbolicOp, Adjoint, Pow, SProd\n\n\n@singledispatch\ndef bind_new_parameters(op: Operator, params: Sequence[TensorLike]) -> Operator:\n    \"\"\"Create a new operator with updated parameters\n\n    This function takes an :class:`~.Operator` and new parameters as input and\n    returns a new operator of the same type with the new parameters. This function\n    does not mutate the original operator.\n\n    Args:\n        op (.Operator): Operator to update\n        params (Sequence[TensorLike]): New parameters to create operator with. This\n            must have the same shape as `op.data`.\n\n    Returns:\n        .Operator: New operator with updated parameters\n    \"\"\"\n    try:\n        return op.__class__(*params, wires=op.wires, **copy.deepcopy(op.hyperparameters))\n    except TypeError:\n        # operation is doing something different with its call signature.\n        new_op = copy.deepcopy(op)\n        new_op.data = tuple(params)\n        return new_op\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_approx_time_evolution(\n    op: qml.ApproxTimeEvolution, params: Sequence[TensorLike]\n):\n    new_hamiltonian = bind_new_parameters(op.hyperparameters[\"hamiltonian\"], params[:-1])\n    time = params[-1]\n    n = op.hyperparameters[\"n\"]\n\n    return qml.ApproxTimeEvolution(new_hamiltonian, time, n)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_commuting_evolution(\n    op: qml.CommutingEvolution, params: Sequence[TensorLike]\n):\n    new_hamiltonian = bind_new_parameters(op.hyperparameters[\"hamiltonian\"], params[1:])\n    freq = op.hyperparameters[\"frequencies\"]\n    shifts = op.hyperparameters[\"shifts\"]\n    time = params[0]\n\n    return qml.CommutingEvolution(new_hamiltonian, time, frequencies=freq, shifts=shifts)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_fermionic_double_excitation(\n    op: qml.FermionicDoubleExcitation, params: Sequence[TensorLike]\n):\n    wires1 = op.hyperparameters[\"wires1\"]\n    wires2 = op.hyperparameters[\"wires2\"]\n\n    return qml.FermionicDoubleExcitation(params[0], wires1=wires1, wires2=wires2)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_angle_embedding(op: qml.AngleEmbedding, params: Sequence[TensorLike]):\n    rotation = op.hyperparameters[\"rotation\"].basis\n    return qml.AngleEmbedding(params[0], wires=op.wires, rotation=rotation)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_identity(op: Identity, params: Sequence[TensorLike]):\n    return qml.Identity(*params, wires=op.wires)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_composite_op(op: CompositeOp, params: Sequence[TensorLike]):\n    new_operands = []\n\n    for operand in op.operands:\n        op_num_params = operand.num_params\n        sub_params = params[:op_num_params]\n        params = params[op_num_params:]\n        new_operands.append(bind_new_parameters(operand, sub_params))\n\n    return op.__class__(*new_operands)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_symbolic_op(op: SymbolicOp, params: Sequence[TensorLike]):\n    new_base = bind_new_parameters(op.base, params)\n    new_hyperparameters = copy.deepcopy(op.hyperparameters)\n    _ = new_hyperparameters.pop(\"base\")\n\n    return op.__class__(new_base, **new_hyperparameters)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_adjoint(op: Adjoint, params: Sequence[TensorLike]):\n    # Need a separate dispatch for `Adjoint` because using a more general class\n    # signature results in a call to `Adjoint.__new__` which doesn't raise an\n    # error but does return an unusable object.\n    return Adjoint(bind_new_parameters(op.base, params))\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_projector(op: Projector, params: Sequence[TensorLike]):\n    # Need a separate dispatch for `Projector` because using a more general class\n    # signature results in a call to `Projector.__new__` which doesn't raise an\n    # error but does return an unusable object.\n    return Projector(*params, wires=op.wires)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_scalar_symbolic_op(op: ScalarSymbolicOp, params: Sequence[TensorLike]):\n    new_scalar = params[0]\n    params = params[1:]\n\n    new_base = bind_new_parameters(op.base, params)\n    new_hyperparameters = copy.deepcopy(op.hyperparameters)\n    _ = new_hyperparameters.pop(\"base\")\n\n    return op.__class__(new_base, new_scalar, **new_hyperparameters)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_sprod(op: SProd, params: Sequence[TensorLike]):\n    # Separate dispatch for `SProd` since its constructor has a different interface\n    new_scalar = params[0]\n    params = params[1:]\n    new_base = bind_new_parameters(op.base, params)\n\n    return SProd(new_scalar, new_base)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_pow(op: Pow, params: Sequence[TensorLike]):\n    # Need a separate dispatch for `Pow` because using a more general class\n    # signature results in a call to `Pow.__new__` which doesn't raise an\n    # error but does return an unusable object.\n    return Pow(bind_new_parameters(op.base, params), op.scalar)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_hamiltonian(op: qml.Hamiltonian, params: Sequence[TensorLike]):\n    return qml.Hamiltonian(params, op.ops)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_tensor(op: Tensor, params: Sequence[TensorLike]):\n    new_obs = []\n\n    for obs in op.obs:\n        sub_params = params[: obs.num_params]\n        params = params[obs.num_params :]\n        new_obs.append(bind_new_parameters(obs, sub_params))\n\n    return Tensor(*new_obs)\n", "path": "pennylane/ops/functions/bind_new_parameters.py"}], "after_files": [{"content": "# Copyright 2018-2023 Xanadu Quantum Technologies Inc.\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n\n#     http://www.apache.org/licenses/LICENSE-2.0\n\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis file contains preprocessings steps that may be called internally\nduring execution.\n\"\"\"\nimport pennylane as qml\nfrom pennylane import math\nfrom pennylane.tape import QuantumScript\n\n\n# pylint: disable=no-member\ndef _convert_op_to_numpy_data(op: qml.operation.Operator) -> qml.operation.Operator:\n    if math.get_interface(*op.data) == \"numpy\":\n        return op\n    # Use operator method to change parameters when it become available\n    return qml.ops.functions.bind_new_parameters(op, math.unwrap(op.data))\n\n\n# pylint: disable=no-member\ndef _convert_measurement_to_numpy_data(\n    m: qml.measurements.MeasurementProcess,\n) -> qml.measurements.MeasurementProcess:\n    if m.obs is None:\n        if m.eigvals() is None or math.get_interface(m.eigvals()) == \"numpy\":\n            return m\n        return type(m)(wires=m.wires, eigvals=math.unwrap(m.eigvals()))\n\n    if math.get_interface(*m.obs.data) == \"numpy\":\n        return m\n    new_obs = qml.ops.functions.bind_new_parameters(m.obs, math.unwrap(m.obs.data))\n    return type(m)(obs=new_obs)\n\n\n# pylint: disable=protected-access\ndef convert_to_numpy_parameters(circuit: QuantumScript) -> QuantumScript:\n    \"\"\"Transforms a circuit to one with purely numpy parameters.\n\n    Args:\n        circuit (QuantumScript): a circuit with parameters of any interface\n\n    Returns:\n        QuantumScript: A circuit with purely numpy parameters\n\n    .. seealso::\n\n        :class:`pennylane.tape.Unwrap` modifies a :class:`~.pennylane.tape.QuantumScript` in place instead of creating\n        a new class. It will also set all parameters on the circuit, not just ones that need to be unwrapped.\n\n    >>> ops = [qml.S(0), qml.RX(torch.tensor(0.1234), 0)]\n    >>> measurements = [qml.state(), qml.expval(qml.Hermitian(torch.eye(2), 0))]\n    >>> circuit = qml.tape.QuantumScript(ops, measurements )\n    >>> new_circuit = convert_to_numpy_parameters(circuit)\n    >>> new_circuit.circuit\n    [S(wires=[0]),\n    RX(0.1234000027179718, wires=[0]),\n    state(wires=[]),\n    expval(Hermitian(array([[1., 0.],\n            [0., 1.]], dtype=float32), wires=[0]))]\n\n    If the component's data does not need to be transformed, it is left uncopied.\n\n    >>> circuit[0] is new_circuit[0]\n    True\n    >>> circuit[1] is new_circuit[1]\n    False\n    >>> circuit[2] is new_circuit[2]\n    True\n    >>> circuit[3] is new_circuit[3]\n    False\n\n    \"\"\"\n    new_ops = (_convert_op_to_numpy_data(op) for op in circuit.operations)\n    new_measurements = (_convert_measurement_to_numpy_data(m) for m in circuit.measurements)\n    new_circuit = circuit.__class__(new_ops, new_measurements, shots=circuit.shots)\n    # must preserve trainable params as we lose information about the machine learning interface\n    new_circuit.trainable_params = circuit.trainable_params\n    new_circuit._qfunc_output = circuit._qfunc_output\n    return new_circuit\n", "path": "pennylane/transforms/convert_to_numpy_parameters.py"}, {"content": "# Copyright 2018-2023 Xanadu Quantum Technologies Inc.\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n\n#     http://www.apache.org/licenses/LICENSE-2.0\n\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"\nThis module contains the qml.bind_new_parameters function.\n\"\"\"\n# pylint: disable=missing-docstring\n\nfrom typing import Sequence\nimport copy\nfrom functools import singledispatch\n\nimport pennylane as qml\nfrom pennylane.typing import TensorLike\nfrom pennylane.operation import Operator, Tensor\n\nfrom ..identity import Identity\nfrom ..qubit import Projector\nfrom ..op_math import CompositeOp, SymbolicOp, ScalarSymbolicOp, Adjoint, Pow, SProd\n\n\n@singledispatch\ndef bind_new_parameters(op: Operator, params: Sequence[TensorLike]) -> Operator:\n    \"\"\"Create a new operator with updated parameters\n\n    This function takes an :class:`~.Operator` and new parameters as input and\n    returns a new operator of the same type with the new parameters. This function\n    does not mutate the original operator.\n\n    Args:\n        op (.Operator): Operator to update\n        params (Sequence[TensorLike]): New parameters to create operator with. This\n            must have the same shape as `op.data`.\n\n    Returns:\n        .Operator: New operator with updated parameters\n    \"\"\"\n    try:\n        return op.__class__(*params, wires=op.wires, **copy.deepcopy(op.hyperparameters))\n    except (TypeError, ValueError):\n        # operation is doing something different with its call signature.\n        new_op = copy.deepcopy(op)\n        new_op.data = tuple(params)\n        return new_op\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_approx_time_evolution(\n    op: qml.ApproxTimeEvolution, params: Sequence[TensorLike]\n):\n    new_hamiltonian = bind_new_parameters(op.hyperparameters[\"hamiltonian\"], params[:-1])\n    time = params[-1]\n    n = op.hyperparameters[\"n\"]\n\n    return qml.ApproxTimeEvolution(new_hamiltonian, time, n)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_commuting_evolution(\n    op: qml.CommutingEvolution, params: Sequence[TensorLike]\n):\n    new_hamiltonian = bind_new_parameters(op.hyperparameters[\"hamiltonian\"], params[1:])\n    freq = op.hyperparameters[\"frequencies\"]\n    shifts = op.hyperparameters[\"shifts\"]\n    time = params[0]\n\n    return qml.CommutingEvolution(new_hamiltonian, time, frequencies=freq, shifts=shifts)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_fermionic_double_excitation(\n    op: qml.FermionicDoubleExcitation, params: Sequence[TensorLike]\n):\n    wires1 = op.hyperparameters[\"wires1\"]\n    wires2 = op.hyperparameters[\"wires2\"]\n\n    return qml.FermionicDoubleExcitation(params[0], wires1=wires1, wires2=wires2)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_angle_embedding(op: qml.AngleEmbedding, params: Sequence[TensorLike]):\n    rotation = op.hyperparameters[\"rotation\"].basis\n    return qml.AngleEmbedding(params[0], wires=op.wires, rotation=rotation)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_identity(op: Identity, params: Sequence[TensorLike]):\n    return qml.Identity(*params, wires=op.wires)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_composite_op(op: CompositeOp, params: Sequence[TensorLike]):\n    new_operands = []\n\n    for operand in op.operands:\n        op_num_params = operand.num_params\n        sub_params = params[:op_num_params]\n        params = params[op_num_params:]\n        new_operands.append(bind_new_parameters(operand, sub_params))\n\n    return op.__class__(*new_operands)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_symbolic_op(op: SymbolicOp, params: Sequence[TensorLike]):\n    new_base = bind_new_parameters(op.base, params)\n    new_hyperparameters = copy.deepcopy(op.hyperparameters)\n    _ = new_hyperparameters.pop(\"base\")\n\n    return op.__class__(new_base, **new_hyperparameters)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_adjoint(op: Adjoint, params: Sequence[TensorLike]):\n    # Need a separate dispatch for `Adjoint` because using a more general class\n    # signature results in a call to `Adjoint.__new__` which doesn't raise an\n    # error but does return an unusable object.\n    return Adjoint(bind_new_parameters(op.base, params))\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_projector(op: Projector, params: Sequence[TensorLike]):\n    # Need a separate dispatch for `Projector` because using a more general class\n    # signature results in a call to `Projector.__new__` which doesn't raise an\n    # error but does return an unusable object.\n    return Projector(*params, wires=op.wires)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_scalar_symbolic_op(op: ScalarSymbolicOp, params: Sequence[TensorLike]):\n    new_scalar = params[0]\n    params = params[1:]\n\n    new_base = bind_new_parameters(op.base, params)\n    new_hyperparameters = copy.deepcopy(op.hyperparameters)\n    _ = new_hyperparameters.pop(\"base\")\n\n    return op.__class__(new_base, new_scalar, **new_hyperparameters)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_sprod(op: SProd, params: Sequence[TensorLike]):\n    # Separate dispatch for `SProd` since its constructor has a different interface\n    new_scalar = params[0]\n    params = params[1:]\n    new_base = bind_new_parameters(op.base, params)\n\n    return SProd(new_scalar, new_base)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_pow(op: Pow, params: Sequence[TensorLike]):\n    # Need a separate dispatch for `Pow` because using a more general class\n    # signature results in a call to `Pow.__new__` which doesn't raise an\n    # error but does return an unusable object.\n    return Pow(bind_new_parameters(op.base, params), op.scalar)\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_hamiltonian(op: qml.Hamiltonian, params: Sequence[TensorLike]):\n    new_H = qml.Hamiltonian(params, op.ops)\n    if op.grouping_indices is not None:\n        new_H.grouping_indices = op.grouping_indices\n    return new_H\n\n\n@bind_new_parameters.register\ndef bind_new_parameters_tensor(op: Tensor, params: Sequence[TensorLike]):\n    new_obs = []\n\n    for obs in op.obs:\n        sub_params = params[: obs.num_params]\n        params = params[obs.num_params :]\n        new_obs.append(bind_new_parameters(obs, sub_params))\n\n    return Tensor(*new_obs)\n", "path": "pennylane/ops/functions/bind_new_parameters.py"}]}