# Quantum NNs with feature gradients

I want to give a quantum NN a set of point locations and optimize an ansantz such that du/dx = 1 with u(x=0) = 0, 0 <= x <= 1. The solution here is a simple, u(x) = x. My question is (1) is the code i wrote doing what I think I it is, and (2) if so, I’ve noticed that it gives back pretty close to linear solutions but with a slope /= 1, even though I am asking it to enforce this. Could this because the quantum solution is only proportional to the answer?
Thanks everyone!

``````import pennylane as qml
from pennylane import numpy as np

dev = qml.device("default.qubit", wires=3)

nlayers = 3
nqbits = 2
max_iterations = 2000 # Maximum number of calls to the optimizer

#shape = qml.StronglyEntanglingLayers.shape(n_layers=nlayers, n_wires=nqbits)
#params = np.random.random(size=shape)

nparams = 3 * nlayers
print("initial params: ",params)

#x = np.array([[0.1, 0.2], [0.3, 0.4], [1.1, 1.2], [1.3, 1.4]], requires_grad=True)
x = np.array([[0.0], [0.3], [0.5], [0.8]], requires_grad=True)

@qml.qnode(dev)
def circuit(params, x):
#qml.RX(x[:, 0], wires=0)
#qml.RY(x[:, 1], wires=1)
#qml.RZ(x[:, 0], wires=2)
qml.templates.AngleEmbedding(x, wires=range(nqbits))

#qml.templates.StronglyEntanglingLayers(params, wires=range(nqbits))

for i in range(0,nlayers):
qml.RX(params[i*(nlayers-1) + 0], wires=[0])
qml.RY(params[i*(nlayers-1) + 1], wires=[1])
qml.CNOT(wires=[0,1])
qml.RY(params[i*(nlayers-1) + 2], wires=[0])

#qml.RX(params[0], wires=0)
#qml.RY(params[1], wires=1)
#qml.RZ(params[2], wires=2)

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

def loss(params, x):
#print(grad_circ(params, x)[0]) # I think* [0] = x, [1] = 1, [2] = params

#print("u_x: ",u_x)
#print("u_xx: ",u_xx)

print("circuit at x=0: ",circuit(params,x[0]))
print("u_x: ",u_x);

cost = np.abs(u_x - 1) + np.abs(circuit(params,x[0]))

return cost

cost = [loss(params,x)] # Store the values of the cost function
for n in range(max_iterations):
(params,  _), prev_cost = opt.step_and_cost(loss,params,x)
cost.append(loss(params,x))
print(f"Step = {n},  Cost function = {cost[-1]:.8f} ")

print("\n" f"Final value of the cost function = {cost[-1]:.8f} ")

plt.semilogy(range(len(cost)), cost)
plt.ylabel("loss")
plt.xlabel("iteration")
``````

Here is an example of the list few lines of output:

Step = 1997, Cost function = 0.04233369
circuit at x=0: Autograd ArrayBox with value 0.0027276330820018013
u_x: Autograd ArrayBox with value 1.039606057608671
circuit at x=0: -0.013977220553959335
u_x: 0.9783536868220091
Step = 1998, Cost function = 0.03562353
circuit at x=0: Autograd ArrayBox with value -0.013977220553959335
u_x: Autograd ArrayBox with value 0.9783536868220091
circuit at x=0: 0.003179064896253525
u_x: 1.0395193985245172
Step = 1999, Cost function = 0.04269846

Final value of the cost function = 0.04269846

I have also attached a plot of the analytic and qml solutions.

Hey @Corey,

Interesting! I’m not sure let’s see if anyone else has any insight!