Source code for psipose.encoders.angle
"""Angle encoding: each feature becomes a rotation angle."""
import pennylane as qml
from ._base import BaseEncoder
[docs]
class AngleEncoder(BaseEncoder):
"""Angle encoding of classical data into quantum rotations.
Each feature :math:`x_i` is encoded as a rotation angle on a separate
qubit via :math:`R_{\\text{axis}}(x_i)`. By default, uses Y rotations.
Supports X, Y, or Z rotations.
This follows the angle encoding approach from:
- Farhi & Neven (2018), "Classification with Quantum Neural Networks
on Near Term Processors" (arXiv:1802.06002). Uses parametrized
rotation gates to encode classical data into quantum states.
- Schuld, Bocharov, Svore & Wiebe (2018), "Circuit-centric
quantum classifiers" (arXiv:1804.00633). Encodes features as
rotation angles in variational quantum circuits.
Mathematically, for a feature vector :math:`\\mathbf{x} = (x_1, \\dots, x_n)`,
the encoded state is:
.. math::
|\\phi(\\mathbf{x})\\rangle = \\bigotimes_{i=1}^{n}
R_{\\text{axis}}(x_i) |0\\rangle
where :math:`R_{\\text{axis}}
\\in \\{R_X, R_Y, R_Z\\}`.
Parameters
----------
rotation : {"X", "Y", "Z"}, default="Y"
Which rotation gate to use for encoding.
n_qubits : int, optional
Number of qubits to use. If None, uses one qubit per feature
(or the minimum of n_features and 10).
Examples
--------
>>> encoder = AngleEncoder(rotation="Y")
>>> encoder.fit(X_train) # determines n_qubits_
>>> circuit = encoder.encode(x_sample, wires=range(encoder.n_qubits_))
"""
def __init__(self, rotation="Y", n_qubits=None):
super().__init__(n_qubits)
if rotation not in {"X", "Y", "Z"}:
raise ValueError(f'rotation must be one of "X", "Y", "Z", got {rotation}')
self.rotation = rotation
[docs]
def encode(self, x, wires):
"""Apply angle encoding to the given wires.
Only encodes as many features as there are wires. If x has more
features than wires, the excess features are truncated.
"""
for i, wire in enumerate(wires):
if i >= len(x):
break
feature = x[i]
if self.rotation == "X":
qml.RX(feature, wires=wire)
elif self.rotation == "Y":
qml.RY(feature, wires=wire)
else: # Z
qml.RZ(feature, wires=wire)