# Why does VQE with pennylane and scikit-optimize gp_minimize give 'func must be scalar' error?

I am trying to replace the SPSA optimizer in the VQE tutorial of pennylane by the bayesian optimizer of scikit-opimize.

When running the code below I get the error "func should return a scalar".

I think this is not actually the problem since my func, wrapped_cost, returns a scalar which I also print. But I have no idea what the real problem is.

import pennylane as qml
from pennylane import qchem
from pennylane import numpy as np
from skopt import gp_minimize

niter_spsa = 200
true_energy = -1.136189454088
seednum=10
num_params=3
devicename="default.qubit"

#setup hamiltonian
symbols = ["H", "H"]
coordinates = np.array([0.0, 0.0, -0.6614, 0.0, 0.0, 0.6614])
h2_ham, num_qubits = qchem.molecular_hamiltonian(symbols, coordinates)

# Variational ansatz for H_2
def circuit(params, wires):  #has 3 parameters
qml.BasisState(np.array([1, 1, 0, 0]), wires=wires)
for i in wires:
qml.Rot(*params[i], wires=i)
qml.CNOT(wires=[2, 3])
qml.CNOT(wires=[2, 0])
qml.CNOT(wires=[3, 1])

dev=qml.device(devicename, wires=num_qubits)

def exp_val_circuit(params):
circuit(params, range(dev.num_wires))
return qml.expval(h2_ham)

##
cost_spsa = qml.QNode(exp_val_circuit, dev)

def wrapped_cost(params):  # Wrapping the cost function and flattening the parameters to be compatible with noisyopt which assumes a flat array of input parameters
return cost_spsa(np.asarray(params).reshape(num_qubits, num_params))

##callback for documentation =^intermediate_results in (3)
def callback_fn(xk):
cost_val = wrapped_cost(xk)

##set initial parameters
np.random.seed(seednum)
init_params = np.random.normal(0, np.pi, (num_qubits, 3), requires_grad=True)
params = list(init_params.copy().reshape(num_qubits * num_params)) #flatten and convert to list (func of gp_minimize takes list as input)

testlist=[i for i in range(12)]
print("Test for wrapped_cost: ",wrapped_cost(testlist), " with tensor list params: ",wrapped_cost(params))

##do optimization
res = gp_minimize(
wrapped_cost,
[(2.0,4.0),(-5.0,0.0),(-6.0,-4.0),(0.0,6.0),
(0.0,2.0),(-3.0,-2.0),(0.0,2.0),(-3.0,0.0),
(-2.0,2.0),(-4.0,0.0),(0.0,2.0),(1.0,4.0)], #search space chosen on basis of observed parameters in minimizeSPSA for seed 10
n_calls=20, #number of calls to the function to be evaluated
n_initial_points=20, #number of evaluations of the function before approximating it with base_estimator
random_state=0, #seed
verbose=True,
callback=callback_fn
)
$$$$


np.asscalar as stated by Catalina solves the described problem.
Further problems (e.g. error message cannot convert (1,) array into (3,4) at np.asscalar(cost_spsa(np.asarray(params).reshape(num_qubits, num_params)))) arise, because xk used in the callbackfunction is not just the set of current parameters as for the Spsa but gp_minimize is much more verbose. Thus, also the additional evaluation of the costfunction in the callback is not needed but it is enough to just output xk` to get all the needed information.