Encoding negative numbers with Möttonen state preparation

I realized that Möttonen State Preparation is able to encode positive real numbers (Ry) and complex numbers(with Ry and Rz), but not negative real values. For example, let’s consider this normalized vector (1/np.sqrt(6), -2/np.sqrt(6), 1/np.sqrt(6), 0.). i can say -2=2exp(pi*1j) and then use Rz gates too. But, when i try to compute the inner product of two vectors with negative numbers with Hadamard Test the result are not true. Is there any other way to encode the negative numbers with only Ry gates? I found a quantum circuit for four vectors with two qubits, but with larger vectors i couldn’t find any paper.
https://iopscience.iop.org/article/10.1088/1751-8121/ac2e27

For two qubits, there is a analytic soultion. But above two qubits i couldn’t find.

Hey @sassan_moradi! Thanks for the interesting question! As far as a feature in PennyLane that solves your problem, it seems like this might not exist at this time. That being said, are you able to share any code? We might be able to help out :grin:

import numpy as np
import pennylane as qml

num_qubits = 3

np.random.seed(0)

dev = qml.device(‘default.qubit’, wires=num_qubits, shots=8192)

x1 = np.array([np.sqrt(0.1), -np.sqrt(0.3), -np.sqrt(0.2), np.sqrt(0.4)])

x2 = np.array([np.sqrt(0.2), -np.sqrt(0.6), np.sqrt(0.1), np.sqrt(0.1)])

def ops(X):

qml.templates.MottonenStatePreparation(X, wires=[1, 2])

ops1 = qml.ctrl(ops, control=0)

@qml.qnode(dev)
def circuit(X1, X2):
qml.Hadamard(wires=0)
ops1(X1)

qml.PauliX(wires=0)

ops1(X2)


qml.PauliX(wires=0)


qml.Hadamard(wires=0)


return qml.expval(qml.PauliZ(0))

res = circuit(x1, x2)

print(2*res-1) # quantum

print(np.inner(x1, x2)) # classic

Thank you for providing that! I’m still a little confused with what it is specifically that you’re trying to do.

It seems like you’re trying to use the Hadamard test for calculating the inner product of the state vectors x1 and x2. But since they are not same (i.e., differ by a global phase), you won’t get the expected result.

when the vector component are negative amplitude encoding (Möttonen) is failed. Yes it is the Global phase. But it doesn’t give the true result even if i use Rz gate. I think this is a new feature that should be added to Pennylane. It is possible to encode negative numbers even with Ry gates. All we need to do is to use another method for computing the angles which i still don’t know.

Admittedly, I’m still a little confused :sweat_smile:. The Mottonen template in terms of how you’re using it is indeed encoding your given input states. If there is a feature that you would like to add to qml.templates.MottonenStatePreparation, maybe this is best-suited as a GitHub issue so that our software team can look at it in more detail :slight_smile:!

You can get started with making a New Feature request here.

Möttonen can encode the absolute value of the vector with neglecting negative sign, if you look at the source code in Pennylane. Ok. i’ll do it.

1 Like

Hi @sassan_moradi! Just adding to what Isaac has mentioned above. While checking the Möttonen template for the x1 and x2 that you have provided, I was able to prepare the states up to a global phase. For example,

dev = qml.device('default.qubit', wires=2)
@qml.qnode(dev)
def circ1(x):
    qml.templates.MottonenStatePreparation(x, wires=[0, 1])
    return qml.state() 

x1 = np.array([np.sqrt(0.1), -np.sqrt(0.3), -np.sqrt(0.2), np.sqrt(0.4)])
x1/np.linalg.norm(x1)
>>> array([ 0.31622777, -0.54772256, -0.4472136 ,  0.63245553]) 
circ1(x1) #global phase = -1j
>>> array([0.-0.31622777j, 0.+0.54772256j, 0.+0.4472136j , 0.-0.63245553j]) 

x2 = np.array([np.sqrt(0.2), -np.sqrt(0.6), np.sqrt(0.1), np.sqrt(0.1)])
x2/np.linalg.norm(x2) 
>>> array([ 0.4472136 , -0.77459667,  0.31622777,  0.31622777])
circ1(x2) #global phase = (1-1j)/sqrt(2)
>>> array([ 0.31622777-0.31622777j, -0.54772256+0.54772256j,
         0.2236068 -0.2236068j ,  0.2236068 -0.2236068j ])
1 Like

this is the original vector array([ 0.31622777, -0.54772256, -0.4472136 , 0.63245553]), but after encoding array([0.-0.31622777j, 0.+0.54772256j, 0.+0.4472136j , 0.-0.63245553j]). This vectors are not the same. Actually i found the solution. I am trying to implement it. Ry(-that) = cos(theta)|0> - sin(theta)|1>. Even with Ry rotation and without Rz gates it is possible to encode the negative numbers.

Would you be able to share your solution? Is this something that can be added as a new feature to PennyLane?

yes. i am trying to implement it. After that i will share it with you.

Awesome! Can’t wait to see it :rocket: