Be it measurement data, images or coordinates in phase-space, almost all forms of data we encounter in day-to-day life are classical. So does it make sense for quantum computers to deal with classical data? The short answer is yes! In this how-to, we will outline the first few steps of how to encode classical data into a quantum state. You will then be able to use this state to perform quantum computations.

# Different embedding types

To encode your classical data into a quantum state, you first have to find out what type of classical data you have. We will distinguish between three different types of data in \(N\)-dimensions.

*Discrete*data, represented as binary \(\mathbf{b} \in \{0, 1\}^{N}\) or integer values \(\mathbf{k} \in \mathbb{Z}^{N}\).- Real
*continuous*data, represented as floating-point values \(\mathbf{x} \in \mathbb{R}^{N}\). - Complex
*continuous*data, represented as complex values \(\boldsymbol{\alpha} \in \mathbb{C}^{2^{N}}\).

Keeping the subset relations \(\{0, 1\}\subset\mathbb{Z}\subset\mathbb{R}\subset\mathbb{C}\) in mind, one could always choose to interpret the data in the domain \(\mathcal{D}\) to be in the superset \(\mathcal{D}^{\prime}\supset \mathcal{D}\).

## 1. Discrete data, represented as binary or integer values

A suitable encoding for binary data is the so-called `BasisEmbedding`

.
The `BasisEmbedding`

class interprets a binary string as a qubit basis state with the following mapping:

See below for a simple example of the `BasisEmbedding`

used to initialize three qubits.

```
import pennylane as qml
N = 3
wires = range(N)
dev = qml.device("default.qubit", wires)
@qml.qnode(dev)
def circuit(b):
qml.BasisEmbedding(b, wires)
return qml.state()
```

```
>>> circuit([1, 1, 1])
[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j]
```

As expected, the result corresponds to the state \(\lvert 111 \rangle = \lvert 1 \rangle \otimes \lvert 1 \rangle \otimes \lvert 1 \rangle\). Representing the \(\lvert 1 \rangle\) state as the second standard basis vector and the tensor product as the Kronecker product, we can confirm the result with a quick calculation.

You can also just pass an integer value to the basis embedding function and it will automatically convert it into its binary representation. We can perform a quick sanity check of this functionality by running

```
>>> print(circuit(7))
[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j]
```

which is the same state vector we saw before. Unsurprisingly, the binary label corresponding to this state vector is also consistent with the binary representation of the integer seven.

## 2. Continuous data, represented as floating-point values

The simplest type of encoding for floating-point data is called `AngleEmbedding`

. This type of embedding encodes a single floating-point value \(x\in \mathbb{R}\) into a quantum state with the mapping

where \(k\in\{x, y, z\}\) is the axis of rotation in the Bloch sphere.
The default axis of rotation is set to \(k=x\) in the `AngleEmbedding`

class. You may also choose to set it to \(k=y\), but make sure to avoid \(k=z\).
The latter case is not useful because every \(x\) will be mapped to the \(|0\rangle\) state; the encoded value will be lost. Note that you can also input a tensor-like object and encode each component as a qubit. Examine the code snippet below to see how to encode a classical floating-point value as a quantum state!

```
import pennylane as qml
from pennylane import numpy as np
N = 3
wires = range(3)
dev = qml.device("default.qubit", wires)
@qml.qnode(dev)
def circuit(val_list):
qml.AngleEmbedding(val_list, wires)
return [qml.expval(qml.PauliZ(w)) for w in wires]
```

```
>>> circuit([0.0, np.pi / 2, np.pi])
tensor([ 1.0, 0.0, -1.0], requires_grad=True)
```

Keep in mind that Pauli rotations are \(2\pi\)-periodic up to a global phase, meaning that you should normalize your data to be in \(\Omega:=[0, \pi)\subset \mathbb{R}\) if possible. This can be helpful in order to avoid encoding two different values as the same quantum state.
While the `AngleEmbedding`

allows you to encode a lot of information in a single qubit, this comes at the cost of a difficult construction process.

## 3. Continuous data, represented as complex values

The last type of embedding we want to look at is the `AmplitudeEmbedding`

. As the name suggests, an array of values can be used as the amplitudes of the state with the mapping

and can be implemented with the following code.

```
import pennylane as qml
N = 3
wires = range(N)
dev = qml.device("default.qubit", wires)
@qml.qnode(dev)
def circuit(features):
qml.AmplitudeEmbedding(features, wires)
return qml.state()
```

```
>>> circuit([0.625, 0.0, 0.0, 0.0, 0.625j, 0.375, 0.25, 0.125])
tensor([0.625+0.j , 0. +0.j , 0. +0.j , 0. +0.j ,
0. +0.625j, 0.375+0.j , 0.25 +0.j , 0.125+0.j ], requires_grad=True)
```

Here, the values were chosen to be normalized, i.e. \(\lVert\boldsymbol{\alpha}\rVert=1\).
Note that one can use unnormalized data by setting the `normalize`

parameter of the `AmplitudeEmbedding`

class to `True`

.

# Conclusion

More advanced embeddings also exist as templated implementations in PennyLane. Besides taking advantage of quantum superposition as we have seen so far, they also take advantage of quantum entanglement. Two such templated embeddings in PennyLane are the `QAOAEmbedding`

and `IQPEmbedding`

. For a complete view of possible embeddings, you can visit the `templates documentation`

. The `BasisEmbedding`

and `AmplitudeEmbedding`

are also covered in the Key Concepts section of the `PennyLane`

website.