# Grad only applies to real scalar-output functions

Hi,
i have the following quantum circuit. I got the error

while trying to optimize the cost function. What can’t i do this?

``````n_qubits = 4 # 4 actions for lunar lander
device = qml.device("default.qubit", wires=n_qubits)

@qml.qnode(device)
def qcircuit(weights, input = None):
AngleEmbedding(input, wires=range(n_qubits))
SEL(weights, wires=range(n_qubits))

return [qml.expval(qml.PauliZ(wires=i)) for i in range(n_qubits)]

def softmax(x):
return [np.exp(i) / np.sum(np.exp(i)) for i in x]

def one_hot(labels, num_labels):
one_hot_diag_matix = np.identity(num_labels)
return [one_hot_diag_matix[i] for i in labels]

def cross_entropy_loss(dist, labels, num_labels):
p = softmax(dist)
one_hot_labels = one_hot(labels,num_labels)

results = []
for pd,l in zip(p,one_hot_labels):
results.append(-np.sum([l[i]*np.log(pd[i]) for i in range(num_labels)]))

return np.mean(results)

def cost(weights, labels, inputs):
predictions = [qcircuit(weights, input=i) for i in inputs]
return cross_entropy_loss(predictions, labels, inputs.shape[1])

max_steps = 60
nlayers = 1

np.random.seed(42)

inputs = np.random.random((10,4))
output = np.random.choice([0,1],10)
weights = 2*np.pi*np.random.random((nlayers,n_qubits,3))

for step in range(max_steps):
weights = opt.step(lambda w: cost(w,output,inputs), weights)
print("{}\n{}".format(step,weights))
print("Cost at step {} ---> {}".format(cost(weights,output, inputs)))``````

I am able to get your code running by replacing the `np.mean(result)` with `np.mean(np.array(result))`. For the autodifferentiation of `np.mean` to work, the input should (as far as I can tell) always be a NumPy array.

The full code is below:

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

n_qubits = 4 # 4 actions for lunar lander
device = qml.device("default.qubit", wires=n_qubits)

@qml.qnode(device)
def qcircuit(weights, input = None):
qml.templates.AngleEmbedding(input, wires=range(n_qubits))
qml.templates.StronglyEntanglingLayers(weights, wires=range(n_qubits))

return [qml.expval(qml.PauliZ(wires=i)) for i in range(n_qubits)]

def softmax(x):
return [np.exp(i) / np.sum(np.exp(i)) for i in x]

def one_hot(labels, num_labels):
one_hot_diag_matix = np.identity(num_labels)
return [one_hot_diag_matix[i] for i in labels]

def cross_entropy_loss(dist, labels, num_labels):
p = softmax(dist)
one_hot_labels = one_hot(labels,num_labels)

results = []
for pd,l in zip(p,one_hot_labels):
results.append(-np.sum([l[i]*np.log(pd[i]) for i in range(num_labels)]))

return np.mean(np.array(results))

def cost(weights, labels, inputs):
predictions = [qcircuit(weights, input=i) for i in inputs]
return cross_entropy_loss(predictions, labels, inputs.shape[1])

max_steps = 60
nlayers = 1

np.random.seed(42)

inputs = np.random.random((10,4))
output = np.random.choice([0,1],10)
weights = qml.init.strong_ent_layers_normal(n_layers=nlayers, n_wires=n_qubits)

for step in range(max_steps):
weights, cost_value = opt.step_and_cost(lambda w: cost(w,output,inputs), weights)
print("{}\n{}".format(step,weights))
print("Cost at step {} ---> {}".format(step, cost_value))
``````

Let me know if this works!

Note that I also made an additional change; I replaced `opt.step` with `opt.step_and_cost()`, which will avoid the overhead of computing the cost function twice. This is a new feature of PennyLane v0.13, released last week.

Hi @josh, thank you so much for your help. I can run the code now

Amazing ! We were all been hoping for this for a while now. Keep on the good work!

3 Likes