Source code for pennylane.templates.embeddings.amplitude

# Copyright 2018-2021 Xanadu Quantum Technologies Inc.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
r"""
Contains the AmplitudeEmbedding template.
"""
# pylint: disable-msg=too-many-branches,too-many-arguments,protected-access
from pennylane.ops import StatePrep

# tolerance for normalization
TOLERANCE = 1e-10


[docs]class AmplitudeEmbedding(StatePrep): r"""Encodes :math:`2^n` features into the amplitude vector of :math:`n` qubits. By setting ``pad_with`` to a real or complex number, ``features`` is automatically padded to dimension :math:`2^n` where :math:`n` is the number of qubits used in the embedding. To represent a valid quantum state vector, the L2-norm of ``features`` must be one. The argument ``normalize`` can be set to ``True`` to automatically normalize the features. If both automatic padding and normalization are used, padding is executed *before* normalizing. Args: features (tensor_like): input tensor of dimension ``(2^len(wires),)``, or less if `pad_with` is specified wires (Any or Iterable[Any]): wires that the template acts on pad_with (float or complex): if not None, the input is padded with this constant to size :math:`2^n` normalize (bool): whether to automatically normalize the features id (str): custom label given to an operator instance, can be useful for some applications where the instance has to be identified validate_norm (bool): whether to validate the norm of the input state Example: Amplitude embedding encodes a normalized :math:`2^n`-dimensional feature vector into the state of :math:`n` qubits: .. code-block:: python import pennylane as qml dev = qml.device('default.qubit', wires=2) @qml.qnode(dev) def circuit(f=None): qml.AmplitudeEmbedding(features=f, wires=range(2)) return qml.expval(qml.Z(0)), qml.state() res, state = circuit(f=[1/2, 1/2, 1/2, 1/2]) The final state of the device is - up to a global phase - equivalent to the input passed to the circuit: >>> state tensor([0.5+0.j, 0.5+0.j, 0.5+0.j, 0.5+0.j], requires_grad=True) **Differentiating with respect to the features** Due to non-trivial classical processing to construct the state preparation circuit, the features argument is in general **not differentiable**. **Normalization** The template will raise an error if the feature input is not normalized. One can set ``normalize=True`` to automatically normalize it: .. code-block:: python @qml.qnode(dev) def circuit(f=None): qml.AmplitudeEmbedding(features=f, wires=range(2), normalize=True) return qml.expval(qml.Z(0)), qml.state() res, state = circuit(f=[15, 15, 15, 15]) >>> state tensor([0.5+0.j, 0.5+0.j, 0.5+0.j, 0.5+0.j], requires_grad=True) **Padding** If the dimension of the feature vector is smaller than the number of amplitudes, one can automatically pad it with a constant for the missing dimensions using the ``pad_with`` option: .. code-block:: python from math import sqrt @qml.qnode(dev) def circuit(f=None): qml.AmplitudeEmbedding(features=f, wires=range(2), pad_with=0.) return qml.expval(qml.Z(0)), qml.state() res, state = circuit(f=[1/sqrt(2), 1/sqrt(2)]) >>> state tensor([0.70710678+0.j, 0.70710678+0.j, 0. +0.j, 0. +0.j], requires_grad=True) """ def __init__( self, features, wires, pad_with=None, normalize=False, id=None, validate_norm=True ): super().__init__( features, wires=wires, pad_with=pad_with, normalize=normalize, validate_norm=validate_norm, id=id, )