Encoding a multi-dimensional vector using amplitude encoding

Hello,

Currently I want to use amplitude encoding for my project. Since for amplitude encoding, it only accepts normalized vector (basically a direction), this would have the problem that for vectors in the same direction with different magnitude, it would result in the same embedding which is not wanted.

I want to know if there are possible ways to also encode the amplitude into the circuit in some clever way provided by Pennylane?

Thank you

Hey @Daniel_Wang! AmplitudeEmbedding has a keyword argument called normalize that normalizes the state automatically for you.

@qml.qnode(dev)
def circuit(f=None):
    qml.AmplitudeEmbedding(features=f, wires=range(2), normalize=True)
    return qml.expval(qml.PauliZ(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)

Let me know if this helps!

Hi,

Thx for the soln! I know it can normalize this for me. My question is actually that, after the normalization, the magnitude information is lost in this process. Think that I have two data: 1) (3, 3) 2) (1, 1), after normalization they are all mapped to the same statevector with the magnitude information lost. I want to know if there is any provided way that could preserve this magnitude information.

Thank you

Thank you for clarifying!

Think that I have two data: 1) (3, 3) 2) (1, 1), after normalization they are all mapped to the same statevector with the magnitude information lost.

I’m not sure that I understand your example here. But, if you want to maintain the magnitude of the feature that you provide AmplitudeEmbedding, you’ll have to compute the normalization yourself:

import pennylane as qml
from pennylane import numpy as np

def random_state():
    """Creates a random 1-qubit state: |psi> = a|0> + phase * b |1>"""
    a = np.random.uniform(-1, 1)
    b = np.random.uniform(-1, 1)
    phase = np.random.uniform(0, 2 * np.pi)
    norm = np.sqrt(a**2 + b**2)

    return np.array([a, np.exp(1j * phase) * b]) / norm, norm

state, normalization = random_state()

dev = qml.device("default.qubit")

@qml.qnode(dev)
def circuit(state):
    qml.AmplitudeEmbedding(state, wires=0)
    return qml.state()

print(circuit(state), normalization)
[-0.92610976+0.j        -0.37080329-0.0694668j] 0.9712434279874106

To your question of embedding the normalization in the circuit somehow, you can try using the normalization as an angle of rotation to a rotation gate:

@qml.qnode(dev)
def circuit(state, normalization):
    qml.AmplitudeEmbedding(state, wires=0)
    qml.RX(normalization, wires=0)
    return qml.state()

Other than that, I’m not sure that there’s a more obvious / clever way to do it :thinking:. Of course, angles of rotation are modulo \pi. So if your normalization is larger than \pi, that information gets lost. Let me know if that helps!

Hi!

Thank you for the answer. That helps.

1 Like

Awesome! Glad I could help :grin: