We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add batching support to the AmplitudeEmbedding template
### Feature details

A recent PR, #1710, added support for creating PennyLane QNodes with *batches* of input parameters via [`@qml.batch_params`](https://pennylane.readthedocs.io/en/latest/code/api/pennylane.batch_params.html). Under the hood, a separate circuit per batch dimension is created, and as a result this approach is both hardware and simulator compatible:

```python
dev = qml.device("default.qubit", wires=2)

@qml.batch_params
@qml.beta.qnode(dev)
def circuit(x, weights):
    qml.RX(x, wires=0)
    qml.RY(0.2, wires=1)
    qml.templates.StronglyEntanglingLayers(weights, wires=[0, 1, 2])
    return qml.expval(qml.Hadamard(0))

def cost(x, weights):
    return np.sum(circuit(x, weights))

batch_size = 3
x = np.linspace(0.1, 0.5, batch_size)
weights = np.random.random((batch_size, 10, 3, 3))

>>> circuit(x, weights)
[-0.30773348  0.23135516  0.13086565]
>>> cost_fn(x, weights)
-0.8581269507766536
>>> qml.grad(cost_fn)(x, weights)[0]
[ 0.23235464  0.00928953 -0.30083487]
```

One such template that would be great to support in batch mode is [`qml.templates.AmplitudeEmbedding`](https://pennylane.readthedocs.io/en/stable/code/api/pennylane.templates.embeddings.AmplitudeEmbedding.html). In order to add support, this template needs to be modified to recognize the first dimension of the input parameter as a _batch_ dimension.

### Implementation

We would like to support the following example:

```python
dev = qml.device("default.qubit", wires=3)

@qml.batch_params
@qml.beta.qnode(dev)
def circuit(data, weights):
    qml.templates.AmplitudeEmbedding(data, wires=[0, 1, 2])
    qml.templates.StronglyEntanglingLayers(weights, wires=[0, 1, 2])
    return qml.expval(qml.PauliX(0))

batch_size = 3

# create a batched input statevector
data = np.random.random((batch_size, 8))
data /= np.linalg.norm(data, axis=1).reshape(-1, 1)  # normalize

weights = np.random.random((batch_size, 10, 3, 3))
circuit(data, weights)
```

This can be done by modifying the `AmplitudeEmbedding` source code as needed. In addition, a test should be added to `tests/transforms/test_batch_params.py`.

Note that some hardware devices do not support `AmplitudeEmbedding` directly, and instead decompose via the [`qml.templates.MottonenStatePreparation`](https://pennylane.readthedocs.io/en/stable/code/api/pennylane.templates.state_preparations.MottonenStatePreparation.html) template, so adding support to this template would also be an added bonus.

### How important would you say this feature is?

2: Somewhat important. Needed this quarter.

### Additional information

_No response_

--- 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/templates/embeddings/amplitude.py`
Content:
```
1 # Copyright 2018-2021 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 r"""
15 Contains the AmplitudeEmbedding template.
16 """
17 # pylint: disable-msg=too-many-branches,too-many-arguments,protected-access
18 import warnings
19 import numpy as np
20 
21 import pennylane as qml
22 from pennylane.operation import Operation, AnyWires
23 from pennylane.ops import QubitStateVector
24 from pennylane.wires import Wires
25 
26 # tolerance for normalization
27 TOLERANCE = 1e-10
28 
29 
30 class AmplitudeEmbedding(Operation):
31     r"""Encodes :math:`2^n` features into the amplitude vector of :math:`n` qubits.
32 
33     By setting ``pad_with`` to a real or complex number, ``features`` is automatically padded to dimension
34     :math:`2^n` where :math:`n` is the number of qubits used in the embedding.
35 
36     To represent a valid quantum state vector, the L2-norm of ``features`` must be one.
37     The argument ``normalize`` can be set to ``True`` to automatically normalize the features.
38 
39     If both automatic padding and normalization are used, padding is executed *before* normalizing.
40 
41     .. note::
42 
43         On some devices, ``AmplitudeEmbedding`` must be the first operation of a quantum circuit.
44 
45     .. warning::
46 
47         At the moment, the ``features`` argument is **not differentiable** when using the template, and
48         gradients with respect to the features cannot be computed by PennyLane.
49 
50     Args:
51         features (tensor_like): input tensor of dimension ``(2^n,)``, or less if `pad_with` is specified
52         wires (Iterable): wires that the template acts on
53         pad_with (float or complex): if not None, the input is padded with this constant to size :math:`2^n`
54         normalize (bool): whether to automatically normalize the features
55         pad (float or complex): same as `pad`, to be deprecated
56 
57     Example:
58 
59         Amplitude embedding encodes a normalized :math:`2^n`-dimensional feature vector into the state
60         of :math:`n` qubits:
61 
62         .. code-block:: python
63 
64             import pennylane as qml
65             from pennylane.templates import AmplitudeEmbedding
66 
67             dev = qml.device('default.qubit', wires=2)
68 
69             @qml.qnode(dev)
70             def circuit(f=None):
71                 AmplitudeEmbedding(features=f, wires=range(2))
72                 return qml.expval(qml.PauliZ(0))
73 
74             circuit(f=[1/2, 1/2, 1/2, 1/2])
75 
76         The final state of the device is - up to a global phase - equivalent to the input passed to the circuit:
77 
78         >>> dev.state
79         [0.5+0.j 0.5+0.j 0.5+0.j 0.5+0.j]
80 
81         **Differentiating with respect to the features**
82 
83         Due to non-trivial classical processing to construct the state preparation circuit,
84         the features argument is in general **not differentiable**.
85 
86         **Normalization**
87 
88         The template will raise an error if the feature input is not normalized.
89         One can set ``normalize=True`` to automatically normalize it:
90 
91         .. code-block:: python
92 
93             @qml.qnode(dev)
94             def circuit(f=None):
95                 AmplitudeEmbedding(features=f, wires=range(2), normalize=True)
96                 return qml.expval(qml.PauliZ(0))
97 
98             circuit(f=[15, 15, 15, 15])
99 
100         >>> dev.state
101         [0.5 + 0.j, 0.5 + 0.j, 0.5 + 0.j, 0.5 + 0.j]
102 
103         **Padding**
104 
105         If the dimension of the feature vector is smaller than the number of amplitudes,
106         one can automatically pad it with a constant for the missing dimensions using the ``pad_with`` option:
107 
108         .. code-block:: python
109 
110             from math import sqrt
111 
112             @qml.qnode(dev)
113             def circuit(f=None):
114                 AmplitudeEmbedding(features=f, wires=range(2), pad_with=0.)
115                 return qml.expval(qml.PauliZ(0))
116 
117             circuit(f=[1/sqrt(2), 1/sqrt(2)])
118 
119         >>> dev.state
120         [0.70710678 + 0.j, 0.70710678 + 0.j, 0.0 + 0.j, 0.0 + 0.j]
121 
122     """
123 
124     num_params = 1
125     num_wires = AnyWires
126     par_domain = "A"
127     grad_method = None
128 
129     def __init__(
130         self, features, wires, pad_with=None, normalize=False, pad=None, do_queue=True, id=None
131     ):
132 
133         # pad is replaced with the more verbose pad_with
134         if pad is not None:
135             warnings.warn(
136                 "The pad argument will be replaced by the pad_with option in future versions of PennyLane.",
137                 UserWarning,
138             )
139             if pad_with is None:
140                 pad_with = pad
141 
142         wires = Wires(wires)
143         self.pad_with = pad_with
144         self.normalize = normalize
145 
146         features = self._preprocess(features, wires, pad_with, normalize)
147         super().__init__(features, wires=wires, do_queue=do_queue, id=id)
148 
149     def adjoint(self):  # pylint: disable=arguments-differ
150         return qml.adjoint(qml.templates.MottonenStatePreparation)(
151             self.parameters[0], wires=self.wires
152         )
153 
154     def expand(self):
155 
156         with qml.tape.QuantumTape() as tape:
157             QubitStateVector(self.parameters[0], wires=self.wires)
158 
159         return tape
160 
161     @staticmethod
162     def _preprocess(features, wires, pad_with, normalize):
163         """Validate and pre-process inputs as follows:
164 
165         * Check that the features tensor is one-dimensional.
166         * If pad_with is None, check that the first dimension of the features tensor
167           has length :math:`2^n` where :math:`n` is the number of qubits. Else check that the
168           first dimension of the features tensor is not larger than :math:`2^n` and pad features with value if necessary.
169         * If normalize is false, check that first dimension of features is normalised to one. Else, normalise the
170           features tensor.
171         """
172 
173         shape = qml.math.shape(features)
174 
175         # check shape
176         if len(shape) != 1:
177             raise ValueError(f"Features must be a one-dimensional tensor; got shape {shape}.")
178 
179         n_features = shape[0]
180         if pad_with is None and n_features != 2 ** len(wires):
181             raise ValueError(
182                 f"Features must be of length {2 ** len(wires)}; got length {n_features}. "
183                 f"Use the 'pad' argument for automated padding."
184             )
185 
186         if pad_with is not None and n_features > 2 ** len(wires):
187             raise ValueError(
188                 f"Features must be of length {2 ** len(wires)} or "
189                 f"smaller to be padded; got length {n_features}."
190             )
191 
192         # pad
193         if pad_with is not None and n_features < 2 ** len(wires):
194             padding = [pad_with] * (2 ** len(wires) - n_features)
195             features = qml.math.concatenate([features, padding], axis=0)
196 
197         # normalize
198         norm = qml.math.sum(qml.math.abs(features) ** 2)
199 
200         if not qml.math.allclose(norm, 1.0, atol=TOLERANCE):
201             if normalize or pad_with:
202                 features = features / np.sqrt(norm)
203             else:
204                 raise ValueError(
205                     f"Features must be a vector of length 1.0; got length {norm}."
206                     "Use 'normalize=True' to automatically normalize."
207                 )
208 
209         features = qml.math.cast(features, np.complex128)
210         return features
211
```
--- 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/templates/embeddings/amplitude.py b/pennylane/templates/embeddings/amplitude.py
--- a/pennylane/templates/embeddings/amplitude.py
+++ b/pennylane/templates/embeddings/amplitude.py
@@ -162,6 +162,7 @@
     def _preprocess(features, wires, pad_with, normalize):
         """Validate and pre-process inputs as follows:
 
+        * If features is batched, the processing that follows is applied to each feature set in the batch.
         * Check that the features tensor is one-dimensional.
         * If pad_with is None, check that the first dimension of the features tensor
           has length :math:`2^n` where :math:`n` is the number of qubits. Else check that the
@@ -170,41 +171,49 @@
           features tensor.
         """
 
-        shape = qml.math.shape(features)
+        # check if features is batched
+        batched = len(qml.math.shape(features)) > 1
 
-        # check shape
-        if len(shape) != 1:
-            raise ValueError(f"Features must be a one-dimensional tensor; got shape {shape}.")
+        features_batch = features if batched else [features]
 
-        n_features = shape[0]
-        if pad_with is None and n_features != 2 ** len(wires):
-            raise ValueError(
-                f"Features must be of length {2 ** len(wires)}; got length {n_features}. "
-                f"Use the 'pad' argument for automated padding."
-            )
-
-        if pad_with is not None and n_features > 2 ** len(wires):
-            raise ValueError(
-                f"Features must be of length {2 ** len(wires)} or "
-                f"smaller to be padded; got length {n_features}."
-            )
+        # apply pre-processing to each features tensor in the batch
+        for i, feature_set in enumerate(features_batch):
+            shape = qml.math.shape(feature_set)
 
-        # pad
-        if pad_with is not None and n_features < 2 ** len(wires):
-            padding = [pad_with] * (2 ** len(wires) - n_features)
-            features = qml.math.concatenate([features, padding], axis=0)
+            # check shape
+            if len(shape) != 1:
+                raise ValueError(f"Features must be a one-dimensional tensor; got shape {shape}.")
 
-        # normalize
-        norm = qml.math.sum(qml.math.abs(features) ** 2)
+            n_features = shape[0]
+            if pad_with is None and n_features != 2 ** len(wires):
+                raise ValueError(
+                    f"Features must be of length {2 ** len(wires)}; got length {n_features}. "
+                    f"Use the 'pad' argument for automated padding."
+                )
 
-        if not qml.math.allclose(norm, 1.0, atol=TOLERANCE):
-            if normalize or pad_with:
-                features = features / np.sqrt(norm)
-            else:
+            if pad_with is not None and n_features > 2 ** len(wires):
                 raise ValueError(
-                    f"Features must be a vector of length 1.0; got length {norm}."
-                    "Use 'normalize=True' to automatically normalize."
+                    f"Features must be of length {2 ** len(wires)} or "
+                    f"smaller to be padded; got length {n_features}."
                 )
 
-        features = qml.math.cast(features, np.complex128)
-        return features
+            # pad
+            if pad_with is not None and n_features < 2 ** len(wires):
+                padding = [pad_with] * (2 ** len(wires) - n_features)
+                feature_set = qml.math.concatenate([feature_set, padding], axis=0)
+
+            # normalize
+            norm = qml.math.sum(qml.math.abs(feature_set) ** 2)
+
+            if not qml.math.allclose(norm, 1.0, atol=TOLERANCE):
+                if normalize or pad_with:
+                    feature_set = feature_set / np.sqrt(norm)
+                else:
+                    raise ValueError(
+                        f"Features must be a vector of norm 1.0; got norm {norm}."
+                        "Use 'normalize=True' to automatically normalize."
+                    )
+
+            features_batch[i] = qml.math.cast(feature_set, np.complex128)
+
+        return features_batch if batched else features_batch[0]

{"golden_diff": "diff --git a/pennylane/templates/embeddings/amplitude.py b/pennylane/templates/embeddings/amplitude.py\n--- a/pennylane/templates/embeddings/amplitude.py\n+++ b/pennylane/templates/embeddings/amplitude.py\n@@ -162,6 +162,7 @@\n     def _preprocess(features, wires, pad_with, normalize):\n         \"\"\"Validate and pre-process inputs as follows:\n \n+        * If features is batched, the processing that follows is applied to each feature set in the batch.\n         * Check that the features tensor is one-dimensional.\n         * If pad_with is None, check that the first dimension of the features tensor\n           has length :math:`2^n` where :math:`n` is the number of qubits. Else check that the\n@@ -170,41 +171,49 @@\n           features tensor.\n         \"\"\"\n \n-        shape = qml.math.shape(features)\n+        # check if features is batched\n+        batched = len(qml.math.shape(features)) > 1\n \n-        # check shape\n-        if len(shape) != 1:\n-            raise ValueError(f\"Features must be a one-dimensional tensor; got shape {shape}.\")\n+        features_batch = features if batched else [features]\n \n-        n_features = shape[0]\n-        if pad_with is None and n_features != 2 ** len(wires):\n-            raise ValueError(\n-                f\"Features must be of length {2 ** len(wires)}; got length {n_features}. \"\n-                f\"Use the 'pad' argument for automated padding.\"\n-            )\n-\n-        if pad_with is not None and n_features > 2 ** len(wires):\n-            raise ValueError(\n-                f\"Features must be of length {2 ** len(wires)} or \"\n-                f\"smaller to be padded; got length {n_features}.\"\n-            )\n+        # apply pre-processing to each features tensor in the batch\n+        for i, feature_set in enumerate(features_batch):\n+            shape = qml.math.shape(feature_set)\n \n-        # pad\n-        if pad_with is not None and n_features < 2 ** len(wires):\n-            padding = [pad_with] * (2 ** len(wires) - n_features)\n-            features = qml.math.concatenate([features, padding], axis=0)\n+            # check shape\n+            if len(shape) != 1:\n+                raise ValueError(f\"Features must be a one-dimensional tensor; got shape {shape}.\")\n \n-        # normalize\n-        norm = qml.math.sum(qml.math.abs(features) ** 2)\n+            n_features = shape[0]\n+            if pad_with is None and n_features != 2 ** len(wires):\n+                raise ValueError(\n+                    f\"Features must be of length {2 ** len(wires)}; got length {n_features}. \"\n+                    f\"Use the 'pad' argument for automated padding.\"\n+                )\n \n-        if not qml.math.allclose(norm, 1.0, atol=TOLERANCE):\n-            if normalize or pad_with:\n-                features = features / np.sqrt(norm)\n-            else:\n+            if pad_with is not None and n_features > 2 ** len(wires):\n                 raise ValueError(\n-                    f\"Features must be a vector of length 1.0; got length {norm}.\"\n-                    \"Use 'normalize=True' to automatically normalize.\"\n+                    f\"Features must be of length {2 ** len(wires)} or \"\n+                    f\"smaller to be padded; got length {n_features}.\"\n                 )\n \n-        features = qml.math.cast(features, np.complex128)\n-        return features\n+            # pad\n+            if pad_with is not None and n_features < 2 ** len(wires):\n+                padding = [pad_with] * (2 ** len(wires) - n_features)\n+                feature_set = qml.math.concatenate([feature_set, padding], axis=0)\n+\n+            # normalize\n+            norm = qml.math.sum(qml.math.abs(feature_set) ** 2)\n+\n+            if not qml.math.allclose(norm, 1.0, atol=TOLERANCE):\n+                if normalize or pad_with:\n+                    feature_set = feature_set / np.sqrt(norm)\n+                else:\n+                    raise ValueError(\n+                        f\"Features must be a vector of norm 1.0; got norm {norm}.\"\n+                        \"Use 'normalize=True' to automatically normalize.\"\n+                    )\n+\n+            features_batch[i] = qml.math.cast(feature_set, np.complex128)\n+\n+        return features_batch if batched else features_batch[0]\n", "issue": "Add batching support to the AmplitudeEmbedding template\n### Feature details\r\n\r\nA recent PR, #1710, added support for creating PennyLane QNodes with *batches* of input parameters via [`@qml.batch_params`](https://pennylane.readthedocs.io/en/latest/code/api/pennylane.batch_params.html). Under the hood, a separate circuit per batch dimension is created, and as a result this approach is both hardware and simulator compatible:\r\n\r\n```python\r\ndev = qml.device(\"default.qubit\", wires=2)\r\n\r\n@qml.batch_params\r\n@qml.beta.qnode(dev)\r\ndef circuit(x, weights):\r\n    qml.RX(x, wires=0)\r\n    qml.RY(0.2, wires=1)\r\n    qml.templates.StronglyEntanglingLayers(weights, wires=[0, 1, 2])\r\n    return qml.expval(qml.Hadamard(0))\r\n\r\ndef cost(x, weights):\r\n    return np.sum(circuit(x, weights))\r\n\r\nbatch_size = 3\r\nx = np.linspace(0.1, 0.5, batch_size)\r\nweights = np.random.random((batch_size, 10, 3, 3))\r\n\r\n>>> circuit(x, weights)\r\n[-0.30773348  0.23135516  0.13086565]\r\n>>> cost_fn(x, weights)\r\n-0.8581269507766536\r\n>>> qml.grad(cost_fn)(x, weights)[0]\r\n[ 0.23235464  0.00928953 -0.30083487]\r\n```\r\n\r\nOne such template that would be great to support in batch mode is [`qml.templates.AmplitudeEmbedding`](https://pennylane.readthedocs.io/en/stable/code/api/pennylane.templates.embeddings.AmplitudeEmbedding.html). In order to add support, this template needs to be modified to recognize the first dimension of the input parameter as a _batch_ dimension.\r\n\r\n### Implementation\r\n\r\nWe would like to support the following example:\r\n\r\n```python\r\ndev = qml.device(\"default.qubit\", wires=3)\r\n\r\n@qml.batch_params\r\n@qml.beta.qnode(dev)\r\ndef circuit(data, weights):\r\n    qml.templates.AmplitudeEmbedding(data, wires=[0, 1, 2])\r\n    qml.templates.StronglyEntanglingLayers(weights, wires=[0, 1, 2])\r\n    return qml.expval(qml.PauliX(0))\r\n\r\nbatch_size = 3\r\n\r\n# create a batched input statevector\r\ndata = np.random.random((batch_size, 8))\r\ndata /= np.linalg.norm(data, axis=1).reshape(-1, 1)  # normalize\r\n\r\nweights = np.random.random((batch_size, 10, 3, 3))\r\ncircuit(data, weights)\r\n```\r\n\r\nThis can be done by modifying the `AmplitudeEmbedding` source code as needed. In addition, a test should be added to `tests/transforms/test_batch_params.py`.\r\n\r\nNote that some hardware devices do not support `AmplitudeEmbedding` directly, and instead decompose via the [`qml.templates.MottonenStatePreparation`](https://pennylane.readthedocs.io/en/stable/code/api/pennylane.templates.state_preparations.MottonenStatePreparation.html) template, so adding support to this template would also be an added bonus.\r\n\r\n### How important would you say this feature is?\r\n\r\n2: Somewhat important. Needed this quarter.\r\n\r\n### Additional information\r\n\r\n_No response_\n", "before_files": [{"content": "# Copyright 2018-2021 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.\nr\"\"\"\nContains the AmplitudeEmbedding template.\n\"\"\"\n# pylint: disable-msg=too-many-branches,too-many-arguments,protected-access\nimport warnings\nimport numpy as np\n\nimport pennylane as qml\nfrom pennylane.operation import Operation, AnyWires\nfrom pennylane.ops import QubitStateVector\nfrom pennylane.wires import Wires\n\n# tolerance for normalization\nTOLERANCE = 1e-10\n\n\nclass AmplitudeEmbedding(Operation):\n    r\"\"\"Encodes :math:`2^n` features into the amplitude vector of :math:`n` qubits.\n\n    By setting ``pad_with`` to a real or complex number, ``features`` is automatically padded to dimension\n    :math:`2^n` where :math:`n` is the number of qubits used in the embedding.\n\n    To represent a valid quantum state vector, the L2-norm of ``features`` must be one.\n    The argument ``normalize`` can be set to ``True`` to automatically normalize the features.\n\n    If both automatic padding and normalization are used, padding is executed *before* normalizing.\n\n    .. note::\n\n        On some devices, ``AmplitudeEmbedding`` must be the first operation of a quantum circuit.\n\n    .. warning::\n\n        At the moment, the ``features`` argument is **not differentiable** when using the template, and\n        gradients with respect to the features cannot be computed by PennyLane.\n\n    Args:\n        features (tensor_like): input tensor of dimension ``(2^n,)``, or less if `pad_with` is specified\n        wires (Iterable): wires that the template acts on\n        pad_with (float or complex): if not None, the input is padded with this constant to size :math:`2^n`\n        normalize (bool): whether to automatically normalize the features\n        pad (float or complex): same as `pad`, to be deprecated\n\n    Example:\n\n        Amplitude embedding encodes a normalized :math:`2^n`-dimensional feature vector into the state\n        of :math:`n` qubits:\n\n        .. code-block:: python\n\n            import pennylane as qml\n            from pennylane.templates import AmplitudeEmbedding\n\n            dev = qml.device('default.qubit', wires=2)\n\n            @qml.qnode(dev)\n            def circuit(f=None):\n                AmplitudeEmbedding(features=f, wires=range(2))\n                return qml.expval(qml.PauliZ(0))\n\n            circuit(f=[1/2, 1/2, 1/2, 1/2])\n\n        The final state of the device is - up to a global phase - equivalent to the input passed to the circuit:\n\n        >>> dev.state\n        [0.5+0.j 0.5+0.j 0.5+0.j 0.5+0.j]\n\n        **Differentiating with respect to the features**\n\n        Due to non-trivial classical processing to construct the state preparation circuit,\n        the features argument is in general **not differentiable**.\n\n        **Normalization**\n\n        The template will raise an error if the feature input is not normalized.\n        One can set ``normalize=True`` to automatically normalize it:\n\n        .. code-block:: python\n\n            @qml.qnode(dev)\n            def circuit(f=None):\n                AmplitudeEmbedding(features=f, wires=range(2), normalize=True)\n                return qml.expval(qml.PauliZ(0))\n\n            circuit(f=[15, 15, 15, 15])\n\n        >>> dev.state\n        [0.5 + 0.j, 0.5 + 0.j, 0.5 + 0.j, 0.5 + 0.j]\n\n        **Padding**\n\n        If the dimension of the feature vector is smaller than the number of amplitudes,\n        one can automatically pad it with a constant for the missing dimensions using the ``pad_with`` option:\n\n        .. code-block:: python\n\n            from math import sqrt\n\n            @qml.qnode(dev)\n            def circuit(f=None):\n                AmplitudeEmbedding(features=f, wires=range(2), pad_with=0.)\n                return qml.expval(qml.PauliZ(0))\n\n            circuit(f=[1/sqrt(2), 1/sqrt(2)])\n\n        >>> dev.state\n        [0.70710678 + 0.j, 0.70710678 + 0.j, 0.0 + 0.j, 0.0 + 0.j]\n\n    \"\"\"\n\n    num_params = 1\n    num_wires = AnyWires\n    par_domain = \"A\"\n    grad_method = None\n\n    def __init__(\n        self, features, wires, pad_with=None, normalize=False, pad=None, do_queue=True, id=None\n    ):\n\n        # pad is replaced with the more verbose pad_with\n        if pad is not None:\n            warnings.warn(\n                \"The pad argument will be replaced by the pad_with option in future versions of PennyLane.\",\n                UserWarning,\n            )\n            if pad_with is None:\n                pad_with = pad\n\n        wires = Wires(wires)\n        self.pad_with = pad_with\n        self.normalize = normalize\n\n        features = self._preprocess(features, wires, pad_with, normalize)\n        super().__init__(features, wires=wires, do_queue=do_queue, id=id)\n\n    def adjoint(self):  # pylint: disable=arguments-differ\n        return qml.adjoint(qml.templates.MottonenStatePreparation)(\n            self.parameters[0], wires=self.wires\n        )\n\n    def expand(self):\n\n        with qml.tape.QuantumTape() as tape:\n            QubitStateVector(self.parameters[0], wires=self.wires)\n\n        return tape\n\n    @staticmethod\n    def _preprocess(features, wires, pad_with, normalize):\n        \"\"\"Validate and pre-process inputs as follows:\n\n        * Check that the features tensor is one-dimensional.\n        * If pad_with is None, check that the first dimension of the features tensor\n          has length :math:`2^n` where :math:`n` is the number of qubits. Else check that the\n          first dimension of the features tensor is not larger than :math:`2^n` and pad features with value if necessary.\n        * If normalize is false, check that first dimension of features is normalised to one. Else, normalise the\n          features tensor.\n        \"\"\"\n\n        shape = qml.math.shape(features)\n\n        # check shape\n        if len(shape) != 1:\n            raise ValueError(f\"Features must be a one-dimensional tensor; got shape {shape}.\")\n\n        n_features = shape[0]\n        if pad_with is None and n_features != 2 ** len(wires):\n            raise ValueError(\n                f\"Features must be of length {2 ** len(wires)}; got length {n_features}. \"\n                f\"Use the 'pad' argument for automated padding.\"\n            )\n\n        if pad_with is not None and n_features > 2 ** len(wires):\n            raise ValueError(\n                f\"Features must be of length {2 ** len(wires)} or \"\n                f\"smaller to be padded; got length {n_features}.\"\n            )\n\n        # pad\n        if pad_with is not None and n_features < 2 ** len(wires):\n            padding = [pad_with] * (2 ** len(wires) - n_features)\n            features = qml.math.concatenate([features, padding], axis=0)\n\n        # normalize\n        norm = qml.math.sum(qml.math.abs(features) ** 2)\n\n        if not qml.math.allclose(norm, 1.0, atol=TOLERANCE):\n            if normalize or pad_with:\n                features = features / np.sqrt(norm)\n            else:\n                raise ValueError(\n                    f\"Features must be a vector of length 1.0; got length {norm}.\"\n                    \"Use 'normalize=True' to automatically normalize.\"\n                )\n\n        features = qml.math.cast(features, np.complex128)\n        return features\n", "path": "pennylane/templates/embeddings/amplitude.py"}], "after_files": [{"content": "# Copyright 2018-2021 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.\nr\"\"\"\nContains the AmplitudeEmbedding template.\n\"\"\"\n# pylint: disable-msg=too-many-branches,too-many-arguments,protected-access\nimport warnings\nimport numpy as np\n\nimport pennylane as qml\nfrom pennylane.operation import Operation, AnyWires\nfrom pennylane.ops import QubitStateVector\nfrom pennylane.wires import Wires\n\n# tolerance for normalization\nTOLERANCE = 1e-10\n\n\nclass AmplitudeEmbedding(Operation):\n    r\"\"\"Encodes :math:`2^n` features into the amplitude vector of :math:`n` qubits.\n\n    By setting ``pad_with`` to a real or complex number, ``features`` is automatically padded to dimension\n    :math:`2^n` where :math:`n` is the number of qubits used in the embedding.\n\n    To represent a valid quantum state vector, the L2-norm of ``features`` must be one.\n    The argument ``normalize`` can be set to ``True`` to automatically normalize the features.\n\n    If both automatic padding and normalization are used, padding is executed *before* normalizing.\n\n    .. note::\n\n        On some devices, ``AmplitudeEmbedding`` must be the first operation of a quantum circuit.\n\n    .. warning::\n\n        At the moment, the ``features`` argument is **not differentiable** when using the template, and\n        gradients with respect to the features cannot be computed by PennyLane.\n\n    Args:\n        features (tensor_like): input tensor of dimension ``(2^n,)``, or less if `pad_with` is specified\n        wires (Iterable): wires that the template acts on\n        pad_with (float or complex): if not None, the input is padded with this constant to size :math:`2^n`\n        normalize (bool): whether to automatically normalize the features\n        pad (float or complex): same as `pad`, to be deprecated\n\n    Example:\n\n        Amplitude embedding encodes a normalized :math:`2^n`-dimensional feature vector into the state\n        of :math:`n` qubits:\n\n        .. code-block:: python\n\n            import pennylane as qml\n            from pennylane.templates import AmplitudeEmbedding\n\n            dev = qml.device('default.qubit', wires=2)\n\n            @qml.qnode(dev)\n            def circuit(f=None):\n                AmplitudeEmbedding(features=f, wires=range(2))\n                return qml.expval(qml.PauliZ(0))\n\n            circuit(f=[1/2, 1/2, 1/2, 1/2])\n\n        The final state of the device is - up to a global phase - equivalent to the input passed to the circuit:\n\n        >>> dev.state\n        [0.5+0.j 0.5+0.j 0.5+0.j 0.5+0.j]\n\n        **Differentiating with respect to the features**\n\n        Due to non-trivial classical processing to construct the state preparation circuit,\n        the features argument is in general **not differentiable**.\n\n        **Normalization**\n\n        The template will raise an error if the feature input is not normalized.\n        One can set ``normalize=True`` to automatically normalize it:\n\n        .. code-block:: python\n\n            @qml.qnode(dev)\n            def circuit(f=None):\n                AmplitudeEmbedding(features=f, wires=range(2), normalize=True)\n                return qml.expval(qml.PauliZ(0))\n\n            circuit(f=[15, 15, 15, 15])\n\n        >>> dev.state\n        [0.5 + 0.j, 0.5 + 0.j, 0.5 + 0.j, 0.5 + 0.j]\n\n        **Padding**\n\n        If the dimension of the feature vector is smaller than the number of amplitudes,\n        one can automatically pad it with a constant for the missing dimensions using the ``pad_with`` option:\n\n        .. code-block:: python\n\n            from math import sqrt\n\n            @qml.qnode(dev)\n            def circuit(f=None):\n                AmplitudeEmbedding(features=f, wires=range(2), pad_with=0.)\n                return qml.expval(qml.PauliZ(0))\n\n            circuit(f=[1/sqrt(2), 1/sqrt(2)])\n\n        >>> dev.state\n        [0.70710678 + 0.j, 0.70710678 + 0.j, 0.0 + 0.j, 0.0 + 0.j]\n\n    \"\"\"\n\n    num_params = 1\n    num_wires = AnyWires\n    par_domain = \"A\"\n    grad_method = None\n\n    def __init__(\n        self, features, wires, pad_with=None, normalize=False, pad=None, do_queue=True, id=None\n    ):\n\n        # pad is replaced with the more verbose pad_with\n        if pad is not None:\n            warnings.warn(\n                \"The pad argument will be replaced by the pad_with option in future versions of PennyLane.\",\n                UserWarning,\n            )\n            if pad_with is None:\n                pad_with = pad\n\n        wires = Wires(wires)\n        self.pad_with = pad_with\n        self.normalize = normalize\n\n        features = self._preprocess(features, wires, pad_with, normalize)\n        super().__init__(features, wires=wires, do_queue=do_queue, id=id)\n\n    def adjoint(self):  # pylint: disable=arguments-differ\n        return qml.adjoint(qml.templates.MottonenStatePreparation)(\n            self.parameters[0], wires=self.wires\n        )\n\n    def expand(self):\n\n        with qml.tape.QuantumTape() as tape:\n            QubitStateVector(self.parameters[0], wires=self.wires)\n\n        return tape\n\n    @staticmethod\n    def _preprocess(features, wires, pad_with, normalize):\n        \"\"\"Validate and pre-process inputs as follows:\n\n        * If features is batched, the processing that follows is applied to each feature set in the batch.\n        * Check that the features tensor is one-dimensional.\n        * If pad_with is None, check that the first dimension of the features tensor\n          has length :math:`2^n` where :math:`n` is the number of qubits. Else check that the\n          first dimension of the features tensor is not larger than :math:`2^n` and pad features with value if necessary.\n        * If normalize is false, check that first dimension of features is normalised to one. Else, normalise the\n          features tensor.\n        \"\"\"\n\n        # check if features is batched\n        batched = len(qml.math.shape(features)) > 1\n\n        features_batch = features if batched else [features]\n\n        # apply pre-processing to each features tensor in the batch\n        for i, feature_set in enumerate(features_batch):\n            shape = qml.math.shape(feature_set)\n\n            # check shape\n            if len(shape) != 1:\n                raise ValueError(f\"Features must be a one-dimensional tensor; got shape {shape}.\")\n\n            n_features = shape[0]\n            if pad_with is None and n_features != 2 ** len(wires):\n                raise ValueError(\n                    f\"Features must be of length {2 ** len(wires)}; got length {n_features}. \"\n                    f\"Use the 'pad' argument for automated padding.\"\n                )\n\n            if pad_with is not None and n_features > 2 ** len(wires):\n                raise ValueError(\n                    f\"Features must be of length {2 ** len(wires)} or \"\n                    f\"smaller to be padded; got length {n_features}.\"\n                )\n\n            # pad\n            if pad_with is not None and n_features < 2 ** len(wires):\n                padding = [pad_with] * (2 ** len(wires) - n_features)\n                feature_set = qml.math.concatenate([feature_set, padding], axis=0)\n\n            # normalize\n            norm = qml.math.sum(qml.math.abs(feature_set) ** 2)\n\n            if not qml.math.allclose(norm, 1.0, atol=TOLERANCE):\n                if normalize or pad_with:\n                    feature_set = feature_set / np.sqrt(norm)\n                else:\n                    raise ValueError(\n                        f\"Features must be a vector of norm 1.0; got norm {norm}.\"\n                        \"Use 'normalize=True' to automatically normalize.\"\n                    )\n\n            features_batch[i] = qml.math.cast(feature_set, np.complex128)\n\n        return features_batch if batched else features_batch[0]\n", "path": "pennylane/templates/embeddings/amplitude.py"}]}